如何正确地使用outlook task的使用.ContinueWith

5天玩转C#并行和多线程编程 —— 第三天 认识和使用Task - 推酷
5天玩转C#并行和多线程编程 —— 第三天 认识和使用Task
对于多线程,我们经常使用的是Thread。在我们了解Task之前,如果我们要使用多核的功能可能就会自己来开线程,然而这种线程模型在.net 4.0之后被一种称为基于“任务的编程模型”所冲击,因为task会比thread具有更小的性能开销,不过大家肯定会有疑惑,任务和线程到底有什么区别呢?
任务和线程的区别:
1、任务是架构在线程之上的,也就是说任务最终还是要抛给线程去执行。
2、任务跟线程不是一对一的关系,比如开10个任务并不是说会开10个线程,这一点任务有点类似线程池,但是任务相比线程池有很小的开销和精确的控制。
&一、认识Task和Task的基本使用
1、认识Task
首先来看一下Task的继承结构。Task标识一个异步操作。
可以看到Task和Thread一样,位于System.Threading命名空间下,这也就是说他们直接有密不可分的联系。下面我们来仔细看一下吧!
2、创建Task
创建Task的方法有两种,一种是直接创建——new一个出来,一种是通过工厂创建。下面来看一下这两种创建方法:
//第一种创建方式,直接实例化
var task1 = new Task(() =&
//TODO you code
这是最简单的创建方法,可以看到其构造函数是一个Action,其构造函数有如下几种,比较常用的是前两种。
//第二种创建方式,工厂创建
var task2 = Task.Factory.StartNew(() =&
//TODO you code
这种方式通过静态工厂,创建以个Task并运行。下面我们来建一个控制台项目,演示一下,代码如下:
要添加System.Threading.Tasks命名控件引用。
using System.Collections.G
using System.L
using System.T
using System.Threading.T
namespace TaskDemo
class Program
static void Main(string[] args)
var task1 = new Task(() =&
Console.WriteLine(&Hello,task&);
task1.Start();
var task2 = Task.Factory.StartNew(() =&
Console.WriteLine(&Hello,task started by task factory&);
Console.Read();
这里我分别用两种方式创建两个task,并让他们运行。可以看到通过构造函数创建的task,必须手动Start,而通过工厂创建的Task直接就启动了。
下面我们来看一下Task的声明周期,编写如下代码:
var task1 = new Task(() =&
Console.WriteLine(&Begin&);
System.Threading.Thread.Sleep(2000);
Console.WriteLine(&Finish&);
Console.WriteLine(&Before start:& + task1.Status);
task1.Start();
Console.WriteLine(&After start:& + task1.Status);
task1.Wait();
Console.WriteLine(&After Finish:& + task1.Status);
Console.Read();
task1.Status就是输出task的当前状态,其输出结果如下:
可以看到调用Start前的状态是Created,然后等待分配线程去执行,到最后执行完成。
从我们可以得出Task的简略生命周期:
Created:表示默认初始化任务,但是“工厂创建的”实例直接跳过。
WaitingToRun: 这种状态表示等待任务调度器分配线程给任务执行。
RanToCompletion:任务执行完毕。
&二、Task的任务控制
Task最吸引人的地方就是他的任务控制了,你可以很好的控制task的执行顺序,让多个task有序的工作。下面来详细说一下:
1、Task.Wait
在上个例子中,我们已经使用过了,task1.Wait();就是等待任务执行完成,我们可以看到最后task1的状态变为Completed。
2、Task.WaitAll
看字面意思就知道,就是等待所有的任务都执行完成,下面我们来写一段代码演示一下:
static void Main(string[] args)
var task1 = new Task(() =&
Console.WriteLine(&Task 1 Begin&);
System.Threading.Thread.Sleep(2000);
Console.WriteLine(&Task 1 Finish&);
var task2 = new Task(() =&
Console.WriteLine(&Task 2 Begin&);
System.Threading.Thread.Sleep(3000);
Console.WriteLine(&Task 2 Finish&);
task1.Start();
task2.Start();
Task.WaitAll(task1, task2);
Console.WriteLine(&All task finished!&);
Console.Read();
其输出结果如下:
可以看到,任务一和任务二都完成以后,才输出All task finished!
3、Task.WaitAny
这个用发同Task.WaitAll,就是等待任何一个任务完成就继续向下执行,将上面的代码WaitAll替换为WaitAny,输出结果如下:
4、Task.ContinueWith
就是在第一个Task完成后自动启动下一个Task,实现Task的延续,下面我们来看下他的用法,编写如下代码:
static void Main(string[] args)
var task1 = new Task(() =&
Console.WriteLine(&Task 1 Begin&);
System.Threading.Thread.Sleep(2000);
Console.WriteLine(&Task 1 Finish&);
var task2 = new Task(() =&
Console.WriteLine(&Task 2 Begin&);
System.Threading.Thread.Sleep(3000);
Console.WriteLine(&Task 2 Finish&);
task1.Start();
task2.Start();
var result = task1.ContinueWith&string&(task =&
Console.WriteLine(&task1 finished!&);
return &This is task result!&;
Console.WriteLine(result.Result.ToString());
Console.Read();
执行结果如下:
可以看到,task1完成之后,开始执行后面的内容,并且这里我们取得task的返回值。
在每次调用ContinueWith方法时,每次会把上次Task的引用传入进来,以便检测上次Task的状态,比如我们可以使用上次Task的Result属性来获取返回值。我们还可以这么写:
var SendFeedBackTask = Task.Factory.StartNew(() =& { Console.WriteLine(&Get some Data!&); })
.ContinueWith&bool&(s =& { return true; })
.ContinueWith&string&(r =&
if (r.Result)
return &Finished&;
return &Error&;
Console.WriteLine(SendFeedBackTask.Result);
首先输出Get some data,然后执行第二个获得返回值true,最后根据判断返回Finished或error。输出结果:
Get some Data!
其实上面的写法简化一下,可以这样写:
Task.Factory.StartNew&string&(() =& {return &One&;}).ContinueWith(ss =& { Console.WriteLine(ss.Result);});
输出One,这个可以看明白了吧~
更多ContinueWith用法参见:/zh-CN/library/dd321405
5、Task的取消
前面说了那么多Task的用法,下面来说下Task的取消,比如我们启动了一个task,出现异常或者用户点击取消等等,我们可以取消这个任务。
如何取消一个Task呢,我们通过cancellation的tokens来取消一个Task。在很多Task的Body里面包含循环,我们可以在轮询的时候判断IsCancellationRequested属性是否为True,如果是True的话就return或者抛出异常,抛出异常后面再说,因为还没有说异常处理的东西。
下面在代码中看下如何实现任务的取消,代码如下:
var tokenSource = new CancellationTokenSource();
var token = tokenSource.T
var task = Task.Factory.StartNew(() =&
for (var i = 0; i & 1000; i++)
System.Threading.Thread.Sleep(1000);
if (token.IsCancellationRequested)
Console.WriteLine(&Abort mission success!&);
}, token);
token.Register(() =&
Console.WriteLine(&Canceled&);
Console.WriteLine(&Press enter to cancel task...&);
Console.ReadKey();
tokenSource.Cancel();
这里开启了一个Task,并给token注册了一个方法,输出一条信息,然后执行ReadKey开始等待用户输入,用户点击回车后,执行tokenSource.Cancel方法,取消任务。其输出结果如下:
好了,今天先说道这里,明天继续讲task,接下来该说说task的异常处理和其他的一些用法,如果喜欢可以关注我,一有更新会马上通知你。
作者:雲霏霏
博客地址:/yunfeifei/
声明:本博客原创文字只代表本人工作中在某一时间内总结的观点或结论,与本人所在单位没有直接利益关系。非商业,未授权,贴子请以现状保留,转载时必须保留此段声明,且在文章页面明显位置给出原文连接。
已发表评论数()
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
排版有问题
没有分页内容
视频无法显示
图片无法显示Task.ContinueWith Method (Action(Task)) (System.Threading.Tasks)
ContinueWith Method (Action(Task))
Expand the table of content
Task.ContinueWith Method (Action&Task&)
.NET Framework 4.6 and 4.5
Creates a continuation that executes asynchronously when the target
completes.Namespace:
mscorlib (in mscorlib.dll)
public Task ContinueWith(
Action&Task& continuationAction
continuationAction
&&An action to run when the
completes. When run, the delegate will be passed the completed task as an argument.
A new continuation .
The continuationAction argument is null.The returned
will not be scheduled for execution until the current task has completed, whether it completes due to running to completion successfully, faulting due to an unhandled exception, or exiting out early due to being canceled.The following example defines a task that populates an array with 100 random date and time values. It uses the ContinueWith(Action&Task&) method to select the earliest and the latest date values once the array is fully populated.
using System.Threading.T
public class Example
public static void Main()
var firstTask = Task.Factory.StartNew( () =& {
Random rnd = new Random();
DateTime[] dates = new DateTime[100];
Byte[] buffer = new Byte[8];
int ctr = dates.GetLowerBound(0);
while (ctr &= dates.GetUpperBound(0)) {
rnd.NextBytes(buffer);
long ticks = BitConverter.ToInt64(buffer, 0);
if (ticks &= DateTime.MinValue.Ticks | ticks &= DateTime.MaxValue.Ticks)
dates[ctr] = new DateTime(ticks);
Task continuationTask = firstTask.ContinueWith( (antecedent) =& {
DateTime[] dates = antecedent.R
DateTime earliest = dates[0];
DateTime latest =
for (int ctr = dates.GetLowerBound(0) + 1; ctr &= dates.GetUpperBound(0); ctr++) {
if (dates[ctr] & earliest) earliest = dates[ctr];
if (dates[ctr] & latest) latest = dates[ctr];
Console.WriteLine("Earliest date: {0}", earliest);
Console.WriteLine("Latest date: {0}", latest);
// Since a console application otherwise terminates, wait for the continuation to complete.
continuationTask.Wait();
// The example displays output like the following:
Earliest date: 2/11/:41 PM
Latest date: 7/29/:49 PM
For an additional example, see .Universal Windows PlatformAvailable since 4.5.NET FrameworkAvailable since 4.0Portable Class LibrarySupported in: SilverlightAvailable since 5.0Windows Phone SilverlightAvailable since 8.0Windows PhoneAvailable since 8.1
IN THIS ARTICLE
Was this page helpful?
Additional feedback?
1500 characters remaining
Thank you!
We appreciate your feedback.
Your feedback about this content is important.Let us know what you think.
Additional feedback?
1500 characters remaining
Thank you!
We appreciate your feedback.
Have a suggestion?
Visit our UserVoice Page to submit and vote on ideas!
Dev centers
Learning resources我是一个靠谱的程序员, 目前关注 MonoTouch、 Mono for Android、 Silverlight、 ASP.NET MVC 以及 NHibernate。已经转到 github , 有问题请到 http://beginor.github.io/about.html 留言, 我会尽量解决!
在 .Net 开发中, 使用 Task 、 Task&T& 进行异步编程是非常方便的, 但是在处理 Task 产生的异常时, 需要注意一个问题, 比如下面的代码:
static Task&int& TestAsync(int a, int b) {
var tcs = new TaskCompletionSource&int&();
Task.Factory.StartNew(() =& {
if (a + b & 0) {
tcs.TrySetException(new InvalidOperationException(&a + b & 0&));
tcs.TrySetResult(a + b);
return tcs.T
当输入的两个参数之和小于 0 时, tcs 会设置一个 InvalidOperationException , 如果直接运行这段代码, 当这个函数返回的 Task 被 GC 回收时, 将会产生 AggregateException was unhandled 的异常, 运行代码如下:
static void Main(string[] args) {
TestAsync(5, -10);
Thread.Sleep(TimeSpan.FromMilliseconds(3000));
GC.Collect();
Console.WriteLine(&Completed.&);
当程序运行结束时, 会产生下图所示的异常:
关键的是这段文字:
A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread.
没有在等待 Task 完成时捕获其异常, 也没有读取 Task 的 Exception 属性, 结果导致异常被终结线程重新抛出。 也就是说, Task 异常有两种处理方式:
1、 调用 Task 的 Wait 方法时使用 try-catch 捕获异常:
var testTask = TestAsync(5, -10);
testTask.Wait();
catch(Exception ex) {
Console.WriteLine(ex);
2、 在 Task 的 ContinueWith 方法中读取 Task 的 Exception 属性:
var testTask = TestAsync(5, -10);
testTask.ContinueWith(task =& {
if (task.IsFaulted) {
Console.WriteLine(task.Exception.GetBaseException());
Console.WriteLine(task.Result);
在 .Net 4.0 、 Sliverlight 5.0 、以及 MonoTouch 中均有类似的问题, 因此, 必须小心翼翼的处理 Task 产生的异常, 否则将会导致你的程序异常退出。
阅读(...) 评论()所有回答(2)
& & & 创建将在指定延迟后完成的任务,返回Task。可以通过await或 Task.Wait() 来达到 Thread.Sleep() 的效果。尽管,Task.Delay() 比 Thread.Sleep() 消耗更多的资源,但是Task.Delay()可用于为方法返回Task类型;或者根据CancellationToken取消标记动态取消等待。
& & & Task.Delay()等待完成返回的Task状态为RanToCompletion;若被取消,返回的Task状态为Canceled。
public static void Test_Delay()
var tokenSource = new CancellationTokenSource();
var token = tokenSource.T
Task.Factory.StartNew(() =& { Thread.Sleep(1000); tokenSource.Cancel(); });
Console.WriteLine("taskDelay1");
Task taskDelay1 = Task.Delay(100000, token);
taskDelay1.Wait();
catch (AggregateException ae)
foreach (var v in ae.InnerExceptions)
Console.WriteLine(ae.Message + " " + v.Message);
taskDelay1.ContinueWith((t) =& Console.WriteLine(t.Status.ToString()));
Thread.Sleep(100);
Console.WriteLine();
Console.WriteLine("taskDelay2");
Task taskDelay2 = Task.Delay(1000);
taskDelay2.ContinueWith((t) =& Console.WriteLine(t.Status.ToString()));
园豆:3629
园豆:3629
MSDN有说明不同:
private async void button1_Click(object sender, EventArgs e)
// Call the method that runs asynchronously.
string result = await WaitAsynchronouslyAsync();
// Call the method that runs synchronously.
//string result = await WaitSynchronously ();
// Display the result.
textBox1.Text +=
// The following method runs asynchronously. The UI thread is not
// blocked during the delay. You can move or resize the Form1 window
// while Task.Delay is running.
public async Task&string& WaitAsynchronouslyAsync()
await Task.Delay(10000);
return "Finished";
// The following method runs synchronously, despite the use of async.
// You cannot move or resize the Form1 window while Thread.Sleep
// is running because the UI thread is blocked.
public async Task&string& WaitSynchronously()
// Add a using directive for System.Threading.
Thread.Sleep(10000);
return "Finished";
地址 :/en-us/library/vstudio/hh156528.aspx
&&&您需要以后才能回答,未注册用户请先。}

我要回帖

更多关于 continue的用法 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信