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

作者:天方 时间:2021-06-26 20:58:17 

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

来源:https://www.cnblogs.com/TianFang/archive/2009/11/02/1594783.html

标签:C#,并行,编程,Task,类
0
投稿

猜你喜欢

  • java金钱处理方法实例详解

    2023-05-29 10:38:29
  • Java8新特性之类型注解_动力节点Java学院整理

    2023-10-10 16:13:07
  • Unity3D选择本地图片并加载

    2023-11-20 09:25:05
  • Springboot日志开启SLF4J过程解析

    2022-04-23 01:29:57
  • Java多线程实现简易微信发红包的方法实例

    2023-04-16 11:46:15
  • Java垃圾回收器的方法和原理总结

    2022-06-27 07:11:46
  • Idea2020.2创建JavaWeb项目(部署Tomcat)方法详解

    2023-11-02 13:29:52
  • Java抽象类、继承及多态和适配器的实现代码

    2021-07-14 05:38:00
  • 使用Maven配置Spring的方法步骤

    2023-02-05 18:37:46
  • 以武侠形式理解Java LinkedList源码

    2021-12-27 20:34:23
  • JAVA字符串占位符使用方法实例

    2021-09-20 17:30:27
  • Java中StringTokenizer的用法简介汇总

    2023-05-29 00:52:24
  • MyBatis动态SQL如何实现前端指定返回字段

    2023-11-28 23:00:58
  • 完美实现ExpandableListView二级分栏效果

    2021-07-18 20:04:13
  • java中多个@Scheduled定时器不执行的解决方法

    2023-03-19 02:32:34
  • C#警惕匿名方法造成的变量共享实例分析

    2021-08-26 19:35:22
  • 浅谈Java消息队列总结篇(ActiveMQ、RabbitMQ、ZeroMQ、Kafka)

    2022-06-13 01:30:40
  • C#使用yield关键字让自定义集合实现foreach遍历的方法

    2022-07-21 11:44:28
  • 详解java 中Spring jsonp 跨域请求的实例

    2023-11-19 02:48:18
  • SpringCloud微服务架构实战之微服务治理功能的实现

    2023-07-20 09:06:38
  • asp之家 软件编程 m.aspxhome.com