C#并行编程Task类用法介绍

C#并行编程Task类用法介绍

Task和ThreadPool的功能类似,可以用来创建一些轻量级的并行任务。对于将一个任务放进线程池

ThreadPool.QueueUserWorkItem(A);

这段代码用Task来实现的话,方式如下:

Task.Factory.StartNew(A);

这两端代码的使用和实现的功能都十分相似。但和TheadPool相比,Task有着更多的功能,更加方便我们使用。

假如我们要创建三个任务,并等待它们完成。这个功能用TheadPool实现如下:

using (ManualResetEvent mre1 = new ManualResetEvent(false)) using (ManualResetEvent mre2 = new ManualResetEvent(false)) using (ManualResetEvent mre3 = new ManualResetEvent(false)) { ThreadPool.QueueUserWorkItem(delegate { A(); mre1.Set(); }); ThreadPool.QueueUserWorkItem(delegate { B(); mre2.Set(); }); ThreadPool.QueueUserWorkItem(delegate { C(); mre3.Set(); }); WaitHandle.WaitAll(new WaitHandle[] { mre1, mre2, mre3 }); }

用Task类实现起来就相对简单多了:

Task t1 = Task.Factory.StartNew(delegate { A(); }); Task t2 = Task.Factory.StartNew(delegate { B(); }); Task t3 = Task.Factory.StartNew(delegate { C(); }); t1.Wait(); t2.Wait(); t3.Wait();

或者我们还可以这么写:

Task t1 = Task.Factory.StartNew(delegate { A(); }); Task t2 = Task.Factory.StartNew(delegate { B(); }); Task t3 = Task.Factory.StartNew(delegate { C(); }); Task.WaitAll(t1, t2, t3);

下面我们来简单的介绍一下Task的基本用法:

创建Task

创建Task有两种方式

通过构造函数创建

Task t1 = new Task(A);

通过TaskFactory创建

Task t1 = Task.Factory.StartNew(A);

这两种方式其实是一样的,第一种方式里面也传入了默认的TaskFactory——Task.Factory。TaskFactory起着对Task进行创建和调度管理的作用,类似于以前CTP版中的TaskManager,关于这个对象,后续会单独写一篇文章介绍。

开始运行Task

在上述两种创建Task方式中,方式1创建的Task并没有立即执行,需要手动调用t1.Start()来执行(类似于线程,需要手动执行)。而方式2创建的Task是立即执行的(类似于线程池,是自动执行的),从这两种方式的函数名称也可以看出这一点。

等待Task完成

等待Task完成的也有两种:

调用Task的成员函数t.Wait()。

调用Task的静态函数Task.WaitAll()或Task.WaitAny()。

这两种方式和.net中常用的WaitHandle差不多,这里就不多介绍了。

取消Task

取消Task的方式较CTP的时候复杂和强大了不少,后续加一个单独的篇章单独介绍。

异常处理

当Task在执行过程中发生异常时,该异常会在Wait或WaitAll等函数中重新throw。可以通过Task的Exception属性来获取发生的异常。

var t1 = Task.Factory.StartNew(() => { throw new Exception("t1 error occor"); }); var t2 = Task.Factory.StartNew(() => { throw new Exception("t2 error occor"); }); try { Task.WaitAll(t1, t2); } catch (Exception) { Console.WriteLine(t1.Exception.InnerException.Message); Console.WriteLine(t2.Exception.InnerException.Message); } 获取Task的返回值

在CTP版本中,是通过Fucture<>类来获取带返回值的Task的,现在已经将类改名为Task<>了,从而实现命名方式的统一。使用方式几乎一致,就是多了一个Result属性,可以在Task执行完成后获取返回值。示例如下:

var t1 = Task.Factory.StartNew(() => 3); t1.Wait(); Console.WriteLine(t1.Result); 其它

在Task中还有不少非常有用的任务调度和错误处理等的方法和属性,它们使得并发操作变得更为强大和简单。

到此这篇关于C#并行编程Task类的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持易知道(ezd.cc)。

推荐阅读

    简单的线程池(三)

    简单的线程池(三),吞吐量,线程,◆ 概要本文中,作者针对 《简单的线程池(一)》 和 《简单的线程池(二)》 介绍的两个线程池分别进行了并发测试。基

    foreach的用法c语言和c#

    foreach的用法c语言和c#,数组,遍历,本文目录foreach的用法c语言和c#详细讲解foreach循环的用法C#中的foreach 怎么用啊foreach用法C#中的f

    params 是什么意思,c#里

    params 是什么意思,c#里,参数,数组,本文目录params 是什么意思,c#里params.add跟params.put有区别吗C#中ref,out和params有什么区别发送请

    C# 基于StackExchange.Redis.dll利用Redis实现分布式Session

    C# 基于StackExchange.Redis.dll利用Redis实现分布式Session,令牌,客户端,最近在研发一款O2O产品,考虑到分布式架构的需要,以前那一套.NET的

    c#中 (ToolStrip

    c#中 (ToolStrip,窗体,控件,本文目录c#中 (ToolStrip)控件是做什么用的winform窗体问题 toolstrip怎么重用,每个窗体都要用到同样的工具栏窗体

    C#取得DataTable最大值、最小值

    C#取得DataTable最大值、最小值,最大值,最小值,C#取得DataTable最大值、最小值int max=int.Parse((dtItemsAll.Compute("Max(CPITEMS_SOR

    线程池大小设置|线程池参数设置

    线程池大小设置|线程池参数设置,,1. 线程池参数设置keepAliveTime(线程存活保持时间)作用:当线程池中线程数大于核心线程数时,线程的空闲时间