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

    Task.ContinueWith

    这货,和 await 一样有“陷阱”。^^,因为写 ContinueWith 不能直观如人的“过程性”思维,写在 ContinueWith 括号里的部分不一定只在发起 ContinueWith 的任务完成后完成,比如这样:

     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") { Entry(); }
    12                 else { break; }
    13             }
    14         }
    15 
    16 
    17         async static void DoWork(string workerName)
    18         {
    19             await Task.Delay(1000);
    20             Console.WriteLine("{0} is working @ Thread Id {1}", workerName, System.Threading.Thread.CurrentThread.ManagedThreadId);
    21         }
    22 
    23         async static void DoClean(string cleaner)
    24         {
    25             await Task.Delay(1000);
    26             Console.WriteLine("{0} is cleaning @ Task Id {1}", cleaner, Task.CurrentId);
    27         }
    28 
    29         async static Task Entry()
    30         {
    31             var task = Task.Factory.StartNew(() => DoWork("工作者1")).
    32                         ContinueWith(backer => DoClean("清理者1")).
    33                         ContinueWith(backer => DoClean("清理者2")).
    34                         ContinueWith(backer => DoClean("清理者3"));
    35         }
    36     }
    37 }

    运行一下试试?如果过程中没有 await Task.Delay 参与,看起来基本是按顺序的,但是这句一加上就立马露陷了,看

    那如何让 ContinueWith 按我们的心思走呢?对了,还有其它参数可以用,让我们随便试试

    1 var task = Task.Factory.StartNew(() => DoWork("工作者1")).
    2                         ContinueWith(backer => DoClean("清理者1"), TaskContinuationOptions.NotOnRanToCompletion).
    3                         ContinueWith(backer => DoClean("清理者2"), TaskContinuationOptions.OnlyOnRanToCompletion).
    4                         ContinueWith(backer => DoClean("清理者3"), TaskContinuationOptions.OnlyOnRanToCompletion);

    运行一下,咦,发生了什么?

    为什么清理者都不工作了?问题出在参数 【TaskContinuationOptions.NotOnRanToCompletion】,它起了作用,它告诉第一个清理者“当工作者任务不是正常完成时你才能启动”,所以清理者1就没有机会启动,它没有机会启动,后面的清理者2、清理者3自然都没有办法启动。到这里只知道 ContinueWith 还有参数可以利用,但是没有达到我们的目的,继续!先把两个 void 方法改造一下

     1 async static Task DoWork(string workerName)
     2 {
     3     await Task.Delay(1000);
     4     Console.WriteLine("{0} is working @ Thread Id {1}", workerName, System.Threading.Thread.CurrentThread.ManagedThreadId);
     5 }
     6 
     7 async static Task DoClean(string cleaner)
     8 {
     9     await Task.Delay(1000);
    10     Console.WriteLine("{0} is cleaning @ Task Id {1}", cleaner, Task.CurrentId);
    11 }

    变成了 Task 的方法,就有了控制的前提条件,接下来改造一下 ContinueWith 的流程

    1 {
    2     var taskWorker = Task.Factory.StartNew(() => DoWork("工作者1"));
    3     await taskWorker.Result;
    4     var c1 = await taskWorker.ContinueWith(backer => DoClean("清理者1"), TaskContinuationOptions.OnlyOnRanToCompletion);
    5     var c2 = await c1.ContinueWith(backer => DoClean("清理者2"), TaskContinuationOptions.OnlyOnRanToCompletion);
    6     var c3 = await c2.ContinueWith(backer => DoClean("清理者3"), TaskContinuationOptions.OnlyOnRanToCompletion);
    7 }

    把原来写在一起的一堆 ContinueWith 分开,让它们各自“拥有身份”,并且按顺序去继承上一个 Task,只有当指定的 Task 执行完成到 RanToCompletion 的状态时自身才被启用,并且 await 的使用保证了 taskWorker 运行完成 C1 才会执行,C1 运行完 C2 才会执行,C2 运行完 C3 才会执行。到此,似乎实现了我们的要求。

  • 相关阅读:
    VOA 2009/11/02 DEVELOPMENT REPORT In Kenya, a Better Life Through Mobile Money
    2009.11.26教育报道在美留学生数量创历史新高
    Java中如何实现Tree的数据结构算法
    The Python Tutorial
    VOA HEALTH REPORT Debate Over New Guidelines for Breast Cancer Screening
    VOA ECONOMICS REPORT Nearly Half of US Jobs Now Held by Women
    VOA ECONOMICS REPORT Junior Achievement Marks 90 Years of Business Education
    VOA 2009/11/07 IN THE NEWS A Second Term for Karzai; US Jobless Rate at 10.2%
    Ant入门
    Python 与系统管理
  • 原文地址:https://www.cnblogs.com/cinlap/p/5762792.html
Copyright © 2011-2022 走看看