Task.ContinueWith

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

 namespace TaskConsole
{
class Program
{
static void Main(string[] args)
{
while (true)
{
var enter = Console.ReadLine(); if (enter.ToLower() == "continue") { Entry(); }
else { break; }
}
} async static void DoWork(string workerName)
{
await Task.Delay();
Console.WriteLine("{0} is working @ Thread Id {1}", workerName, System.Threading.Thread.CurrentThread.ManagedThreadId);
} async static void DoClean(string cleaner)
{
await Task.Delay();
Console.WriteLine("{0} is cleaning @ Task Id {1}", cleaner, Task.CurrentId);
} async static Task Entry()
{
var task = Task.Factory.StartNew(() => DoWork("工作者1")).
ContinueWith(backer => DoClean("清理者1")).
ContinueWith(backer => DoClean("清理者2")).
ContinueWith(backer => DoClean("清理者3"));
}
}
}

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

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

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

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

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

 async static Task DoWork(string workerName)
{
await Task.Delay();
Console.WriteLine("{0} is working @ Thread Id {1}", workerName, System.Threading.Thread.CurrentThread.ManagedThreadId);
} async static Task DoClean(string cleaner)
{
await Task.Delay();
Console.WriteLine("{0} is cleaning @ Task Id {1}", cleaner, Task.CurrentId);
}

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

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

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

.Net 异步随手记(二)的更多相关文章

  1. .Net 异步随手记(三)

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

  2. python异步IO编程(二)

    python异步IO编程(二) 目录 开门见山 Async IO设计模式 事件循环 asyncio 中的其他顶层函数 开门见山 下面我们用两个简单的例子来让你对异步IO有所了解 import asyn ...

  3. Javascript异步编程之二回调函数

    上一节讲异步原理的时候基本上把回掉函数也捎带讲了一些,这节主要举几个例子来具体化一下.在开始之前,首先要明白一件事,在javascript里函数可以作为参数进行传递,这里涉及到高阶函数的概念,大家可以 ...

  4. 异步编程(二)基于事件的异步编程模式 (EAP)

    一.引言 在上一个专题中为大家介绍了.NET 1.0中提出来的异步编程模式——APM,虽然APM为我们实现异步编程提供了一定的支持,同时它也存在着一些明显的问题——不支持对异步操作的取消和没有提供对进 ...

  5. ASP.NET Core 3.x启动时运行异步任务(二)

    这一篇是接着前一篇在写的.如果没有看过前一篇文章,建议先去看一下前一篇,这儿是传送门   一.前言 前一篇文章,我们从应用启动时异步运行任务开始,说到了必要性,也说到了几种解决方法,及各自的优缺点.最 ...

  6. C#异步编程(二)

    async和await结构 序 前篇博客异步编程系列(一) 已经介绍了何谓异步编程,这篇主要介绍怎么实现异步编程,主要通过C#5.0引入的async/await来实现. BeginInvoke和End ...

  7. 浅析Netty的异步事件驱动(二)

    上一篇文件浅析了Netty中的事件驱动过程,这篇主要写一下异步相关的东东. 首先,什么是异步了? 异步的概念和同步相对.当一个异步过程调用发出后,调用者不能立刻得到结果.实际处理这个调用的部件在完成后 ...

  8. .Net 异步随手记(一)

    今天要记录的内容摘要是: 什么时候异步代码能“等”在那里,什么时候不会“等” 这两天Coding的时候碰到一个事儿,就是想让异步等在那里结果却直接执行过去了,比如这样: async static vo ...

  9. django celery的分布式异步之路(二) 高并发

    当你跑通了前面一个demo,博客地址:http://www.cnblogs.com/kangoroo/p/7299920.html,那么你的分布式异步之旅已经起步了. 性能和稳定性是web服务的核心评 ...

随机推荐

  1. Swift学习笔记(一)搭配环境以及代码运行成功

    原文:Swift学习笔记(一)搭配环境以及代码运行成功 1.Swift是啥? 百度去!度娘告诉你它是苹果最新推出的编程语言,比c,c++,objc要高效简单.能够开发ios,mac相关的app哦!是苹 ...

  2. 浅谈 js 正则之 test 方法

    原文:浅谈 js 正则之 test 方法 其实我很少用这个,所以之前一直没注意这个问题,自从落叶那厮写了个变态的测试我才去看了下这东西.先来看个东西吧. var re = /\d/; console. ...

  3. C#5.0新特性

    C#5.0新特性 C#5.0最大的新特性,莫过于Async和Parallel. 以往我们为了让用户界面保持相应,我们可以直接使用异步委托或是System.Threading命名空间中的成员,但Syst ...

  4. WebBrowser控件的简单应用2

    原文:WebBrowser控件的简单应用2 第一个简单应用里面讲述的是如何模拟调用当前网页的元素的事件或者赋值/取值.这次的应用讲述的是1:如何处理弹出新页面的事件(总是在我的浏览器里面现实新页面)2 ...

  5. vector查找元素

    转自:http://hi.baidu.com/chain2008/blog/item/821744585e12c5c89c8204e8.html 今天又忘了怎么在vector中查找某一个值..唉..每 ...

  6. json.net 比jsonIgnore 更好的方法 修改源码

    关于 JsonIgnore  问题, EF T4 模板 中 存在主外键关系 namespace WindowsFormsApplication1{    using System;    using ...

  7. 枚举 UIButton补充

    一.URL 1.什么是URL? URL是某个资源的唯一路径,通过这个路径就能访问对应的资源 2.URL的组成 协议头://全路径 * 协议头就代表资源的类型,比如http代表网络服务器资源,ftp代表 ...

  8. Spring之SpringMVC的RequestToViewNameTranslator(源码)分析

    前言 SpringMVC如果在处理业务的过程中发生了异常,这个时候是没有一个完整的ModelAndView对象返回的,它应该是怎么样处理呢?或者说应该怎么去获取一个视图然后去展示呢.下面就是要讲的Re ...

  9. windows下oracle数据库定时备份与压缩批处理脚本(win7/win2008亲测通过)

    第一种方式:全备份,并直接覆盖原来的备份文件,固定命名. 脚本: @echo off exp system/a123@HZPG file=e:\db_backup\oradata.dmp log=e: ...

  10. Mac OSX操作系统安装和配置Zend Server 6教程(3)

    Zend Server安装好以后,在php.ini文件中,没有默认时区.就是导致很多警告信息出现的根本. 接下来,我们看看如果修改这个文件. 首先,进入php.ini文件.此文件在目录zend/etc ...