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. 图解zookeeper FastLeader选举算法

    zookeeper当配置为群集模式,在启动或异常情况将被选举为的例子Leader.默认选择算法FastLeaderElection. 不知道zookeeper够考虑这样一个问题:某个服务能够配置为多个 ...

  2. crawler_分布式网络爬虫的设计与实现_设计图

    一.集中调度式 二.p2p 三.混合调度式 四.大型集群

  3. LeetCode——Flatten Binary Tree to Linked List

    Given a binary tree, flatten it to a linked list in-place. For example, Given 1 / \ 2 5 / \ \ 3 4 6 ...

  4. JS里写入(混写)php asp

    原文:JS里写入(混写)php asp JS里写入(混写)php 方法1:<Br> <script language="javascript"> docum ...

  5. 《java系统性能调优》--1.发现瓶颈

    性能啊!性能! 之所以想写写性能调优,也是有感于我们的项目,我们採用一些手段使得系统性能上升了一个台阶,总是须要把这点经验沉淀一下.随着工作的深入,关于系统性能的事肯定还有非常多,也算是通过这个系列文 ...

  6. asp.net 一般处理程序session 为 null

    必须继承  IRequiresSessionState  接口才行!

  7. Socket 学习(三).5 UDP 的弱点

    前面 讲到了,udp 传输文本的例子,发现 udp 确实 比tcp 高效一些,现在我用来传输文件,问题果然来了,结果发现 他不能一次 传输大于 64K的东西! 那么 我自然想到了 切包,多次发送,再合 ...

  8. JS 数组array方法push, pop, unshift, shift, slice,splice,contact, join, sort

    Array:数组对象用来在单独的变量名中存储一系列的值   定义数组:         1. var arrayObj = new Array();         2. var arrayObj = ...

  9. PKU 1276 Cash Machine

    <span style="color:#000099;">/* Cash Machine Time Limit: 1000MS Memory Limit: 10000K ...

  10. Postman (Chrome插件)

    接口测试从未如此简单 - Postman (Chrome插件) Posted on 2015-01-16 15:50 WadeXu 阅读(468) 评论(7) 编辑 收藏 接口测试从未如此简单 - P ...