• 取消task异步任务


    1、任务取消

    System.Threading.Tasks.Task 和 System.Threading.Tasks.Task 类支持通过使用取消标记进行取消。 有关详细信息,请参阅托管线程中的取消。 在 Task 类中,取消涉及用户委托间的协作,这表示可取消的操作和请求取消的代码。 成功取消涉及调用 CancellationTokenSource.Cancel 方法的请求代码,以及及时终止操作的用户委托。 可以使用以下选项之一终止操作:

    • 简单地从委托中返回。 在许多情况下,这样已足够;但是,采用这种方式取消的任务实例会转换为 TaskStatus.RanToCompletion 状态,而不是 TaskStatus.Canceled 状态。

    • 引发 OperationCanceledException ,并将其传递到在其上请求了取消的标记。 完成此操作的首选方式是使用 ThrowIfCancellationRequested 方法。 采用这种方式取消的任务会转换为 Canceled 状态,调用代码可使用该状态来验证任务是否响应了其取消请求。

    下面的示例演示引发异常的任务取消的基本模式。 请注意,标记将传递到用户委托和任务实例本身

    1. using System;
    2. using System.Threading;
    3. using System.Threading.Tasks;
    4. class Program
    5. {
    6. static async Task Main()
    7. {
    8. var tokenSource2 = new CancellationTokenSource();
    9. CancellationToken ct = tokenSource2.Token;
    10. var task = Task.Run(() =>
    11. {
    12. // Were we already canceled?
    13. ct.ThrowIfCancellationRequested();
    14. bool moreToDo = true;
    15. while (moreToDo)
    16. {
    17. // Poll on this property if you have to do
    18. // other cleanup before throwing.
    19. if (ct.IsCancellationRequested)
    20. {
    21. // Clean up here, then...
    22. ct.ThrowIfCancellationRequested();
    23. }
    24. }
    25. }, tokenSource2.Token); // Pass same token to Task.Run.
    26. tokenSource2.Cancel();
    27. // Just continue on this thread, or await with try-catch:
    28. try
    29. {
    30. await task;
    31. }
    32. catch (OperationCanceledException e)
    33. {
    34. Console.WriteLine($"{nameof(OperationCanceledException)} thrown with message: {e.Message}");
    35. }
    36. finally
    37. {
    38. tokenSource2.Dispose();
    39. }
    40. Console.ReadKey();
    41. }
    42. }

    2、如何:取消任务及其子级

    这些示例展示了如何执行下列任务:

    1. 创建并启动可取消任务。

    2. 将取消令牌传递给用户委托,并视需要传递给任务实例。

    3. 注意并响应用户委托中的取消请求。

    4. (可选)注意已取消任务的调用线程。

    调用线程不会强制结束任务,只会提示取消请求已发出。 如果任务已在运行,至于怎样才能注意请求并适当响应,取决于用户委托的选择。 如果取消请求在任务运行前发出,用户委托绝不会执行,任务对象的状态会转换为“已取消”。

    示例

    此示例展示了如何终止 Task 及其子级,以响应取消请求。 还会演示,当用户委托通过引发 TaskCanceledException 终止时,调用线程可以选择使用 Wait 方法或 WaitAll 方法来等待任务完成。 在这种情况下,必须使用 try/catch 块来处理调用线程上的异常。

    1. using System;
    2. using System.Collections.Concurrent;
    3. using System.Threading;
    4. using System.Threading.Tasks;
    5. public class Example
    6. {
    7. public static async Task Main()
    8. {
    9. var tokenSource = new CancellationTokenSource();
    10. var token = tokenSource.Token;
    11. // Store references to the tasks so that we can wait on them and
    12. // observe their status after cancellation.
    13. Task t;
    14. var tasks = new ConcurrentBag();
    15. Console.WriteLine("Press any key to begin tasks...");
    16. Console.ReadKey(true);
    17. Console.WriteLine("To terminate the example, press 'c' to cancel and exit...");
    18. Console.WriteLine();
    19. // Request cancellation of a single task when the token source is canceled.
    20. // Pass the token to the user delegate, and also to the task so it can
    21. // handle the exception correctly.
    22. t = Task.Run(() => DoSomeWork(1, token), token);
    23. Console.WriteLine("Task {0} executing", t.Id);
    24. tasks.Add(t);
    25. // Request cancellation of a task and its children. Note the token is passed
    26. // to (1) the user delegate and (2) as the second argument to Task.Run, so
    27. // that the task instance can correctly handle the OperationCanceledException.
    28. t = Task.Run(() =>
    29. {
    30. // Create some cancelable child tasks.
    31. Task tc;
    32. for (int i = 3; i <= 10; i++)
    33. {
    34. // For each child task, pass the same token
    35. // to each user delegate and to Task.Run.
    36. tc = Task.Run(() => DoSomeWork(i, token), token);
    37. Console.WriteLine("Task {0} executing", tc.Id);
    38. tasks.Add(tc);
    39. // Pass the same token again to do work on the parent task.
    40. // All will be signaled by the call to tokenSource.Cancel below.
    41. DoSomeWork(2, token);
    42. }
    43. }, token);
    44. Console.WriteLine("Task {0} executing", t.Id);
    45. tasks.Add(t);
    46. // Request cancellation from the UI thread.
    47. char ch = Console.ReadKey().KeyChar;
    48. if (ch == 'c' || ch == 'C')
    49. {
    50. tokenSource.Cancel();
    51. Console.WriteLine("\nTask cancellation requested.");
    52. // Optional: Observe the change in the Status property on the task.
    53. // It is not necessary to wait on tasks that have canceled. However,
    54. // if you do wait, you must enclose the call in a try-catch block to
    55. // catch the TaskCanceledExceptions that are thrown. If you do
    56. // not wait, no exception is thrown if the token that was passed to the
    57. // Task.Run method is the same token that requested the cancellation.
    58. }
    59. try
    60. {
    61. await Task.WhenAll(tasks.ToArray());
    62. }
    63. catch (OperationCanceledException)
    64. {
    65. Console.WriteLine($"\n{nameof(OperationCanceledException)} thrown\n");
    66. }
    67. finally
    68. {
    69. tokenSource.Dispose();
    70. }
    71. // Display status of all tasks.
    72. foreach (var task in tasks)
    73. Console.WriteLine("Task {0} status is now {1}", task.Id, task.Status);
    74. }
    75. static void DoSomeWork(int taskNum, CancellationToken ct)
    76. {
    77. // Was cancellation already requested?
    78. if (ct.IsCancellationRequested)
    79. {
    80. Console.WriteLine("Task {0} was cancelled before it got started.",
    81. taskNum);
    82. ct.ThrowIfCancellationRequested();
    83. }
    84. int maxIterations = 100;
    85. // NOTE!!! A "TaskCanceledException was unhandled
    86. // by user code" error will be raised here if "Just My Code"
    87. // is enabled on your computer. On Express editions JMC is
    88. // enabled and cannot be disabled. The exception is benign.
    89. // Just press F5 to continue executing your code.
    90. for (int i = 0; i <= maxIterations; i++)
    91. {
    92. // Do a bit of work. Not too much.
    93. var sw = new SpinWait();
    94. for (int j = 0; j <= 100; j++)
    95. sw.SpinOnce();
    96. if (ct.IsCancellationRequested)
    97. {
    98. Console.WriteLine("Task {0} cancelled", taskNum);
    99. ct.ThrowIfCancellationRequested();
    100. }
    101. }
    102. }
    103. }
    104. // The example displays output like the following:
    105. // Press any key to begin tasks...
    106. // To terminate the example, press 'c' to cancel and exit...
    107. //
    108. // Task 1 executing
    109. // Task 2 executing
    110. // Task 3 executing
    111. // Task 4 executing
    112. // Task 5 executing
    113. // Task 6 executing
    114. // Task 7 executing
    115. // Task 8 executing
    116. // c
    117. // Task cancellation requested.
    118. // Task 2 cancelled
    119. // Task 7 cancelled
    120. //
    121. // OperationCanceledException thrown
    122. //
    123. // Task 2 status is now Canceled
    124. // Task 1 status is now RanToCompletion
    125. // Task 8 status is now Canceled
    126. // Task 7 status is now Canceled
    127. // Task 6 status is now RanToCompletion
    128. // Task 5 status is now RanToCompletion
    129. // Task 4 status is now RanToCompletion
    130. // Task 3 status is now RanToCompletion

  • 相关阅读:
    JVM运行时数据区
    【java学习—十五】创建多线程的两种方式(2)
    【数据结构-树】并查集的定义及其操作
    排序算法优化(二)
    Docker实践笔记7:构建MySQL 8镜像
    Unity与CocosCreator对比学习二
    2022年大一学生实训作业【基于HTML+CSS制作中华传统文化传统美德网站 (6页面)】
    【JUC】9.对象内存布局
    Junit4 一直处于运行中的排查过程
    【OpenCV-Torch-dlib-ubuntu】Vm虚拟机linux环境摄像头调用方法与dilb模型探究
  • 原文地址:https://blog.csdn.net/xujianjun229/article/details/126389080