zoukankan      html  css  js  c++  java
  • .Net 异步随手记(三)

    从《.Net 异步随手记(二)》来看,总感觉还差点儿什么,就是对不同情况的处理。比如当一个 Task 完成了后,我想让它继续执行 T1,如果被取消了就去执行 T2,如果...就去执行 T3,那怎么写呢?

    过程是痛苦的,我笨了两天,终于搞通了。之前一直疑惑,为什么引发了 CancellationTokenSource 的 Cancel 方法,捕捉到的 Task 的 IsCanceled 属性依然是 False,今天晚上终于捕捉到了,看来还是自己写的有问题,不废话了,把代码记录一下:

     1 namespace TaskConsole
     2 {
     3     class Program
     4     {
     5         static void Main(string[] args)
     6         {
     7             while (true)
     8             {
     9                 var enter = Console.ReadLine();
    10 
    11                 if (enter.ToLower() == "continue")
    12                 {
    13                     cancelSource = new CancellationTokenSource();
    14                     token = cancelSource.Token;
    15                     var task = Entry();
    16                     Console.WriteLine(task.Status);
    17                 }
    18                 else if(enter.ToLower() == "cel") {
    19                     cancelSource.Cancel();
    20                 }
    21                 else { break; }
    22             }
    23         }
    24 
    25 
    26         async static Task DoWork(string workerName)
    27         {
    28             int count = 0;
    29 
    30             while (count<10)
    31             {
    32                 if (token.IsCancellationRequested)
    33                 {
    34                     Console.WriteLine("用户主动取消了任务");
    35                     token.ThrowIfCancellationRequested();
    36                 }
    37 
    38                 count++;
    39                 Console.WriteLine("{0} count {1} @ Thread Id {2}", workerName, count, System.Threading.Thread.CurrentThread.ManagedThreadId);
    40                 await Task.Delay(2000);
    41             }            
    42         }
    43 
    44         async static Task DoCancel(Task callbacker)
    45         {
    46             //await Task.Delay(2000);
    47             Console.WriteLine("Do Cancel 任务运行了");
    48         }
    49 
    50         async static Task DoContinue(Task callbacker)
    51         {
    52             //await Task.Delay(1000);
    53             //Console.WriteLine("Continue 任务运行了 @ Task is {1}", callbacker.Status);
    54             Console.WriteLine("Do Continue 运行了");
    55         }
    56 
    57         async static Task Entry()
    58         {
    59             {
    60                 var taskWorker = Task.Factory.StartNew(() => DoWork("工作者1"));
    61                 try
    62                 {
    63                     await taskWorker.Result;
    64                     Console.WriteLine("taskworker 已经完成,是被取消的? {0}", taskWorker.Result.IsCanceled);
    65                 }
    66                 catch (OperationCanceledException)
    67                 {
    68                     Console.WriteLine("OperationCanceledException 异常,任务是被取消的? {0}", taskWorker.Result.IsCanceled);
    69                 }
    70                 
    71                 var c1 = taskWorker.Result.ContinueWith(backer => DoCancel(backer), TaskContinuationOptions.OnlyOnCanceled);
    72                 var c2 = taskWorker.Result.ContinueWith(backer => DoContinue(backer), TaskContinuationOptions.OnlyOnRanToCompletion);
    73             }
    74         }
    75 
    76         static CancellationTokenSource cancelSource;
    77         static CancellationToken token;
    78     }
    79 }

    从代码可以看出,C1 = 的是 taskWorker 的 Result 的 ContinueWith,也就是说,Token 真正引发的取消操作是作用于 DoWork 方法内的,而 taskWorker 并不是 DoWork 这个异步方法的引用,而是被 Factory“创建出来的某个运行 DoWork 的 Task”。因此,想要 C1、C2起作用,必须侦测的是 DoWork 方法到底是完成了还是被取消了,而 DoWork 方法是 taskWorker 的 Result,因此代码写成这样,运行结果就正确了。

    输入 continue 启动程序,如果正常执行结束,将会是这样

    中途输入 cel 来手动取消,将会是这样

    感谢自己这脑袋终于想明白了,总结,如果写的是

    1 var c1 = taskWorker.ContinueWith(backer => DoCancel(backer), TaskContinuationOptions.OnlyOnCanceled);
    2 var c2 = taskWorkert.ContinueWith(backer => DoContinue(backer), TaskContinuationOptions.OnlyOnRanToCompletion);

    那 C1 就永远不会有机会运行了,因为无论 DoWork 是正常结束还是被取消了,被工厂创建出来的那个 Task (也就是 taskWorker 所指向的对象)在 DoWork 返回之后都是 RanToCompletion。

  • 相关阅读:
    mac允许安装任何来源的软件
    Xcode Edit Schemes
    认识下算法工程师
    一定要熟练地使用常用的Foundation服务
    常用的UI控件
    认识iOS系统架构
    深拷贝/浅拷贝的理解
    Create Fiori List App Report with ABAP CDS view – PART 1
    [転載]SAP S/4HANAトライアル環境でCDS Viewを確認
    ABAP CDS
  • 原文地址:https://www.cnblogs.com/cinlap/p/5763287.html
Copyright © 2011-2022 走看看