zoukankan      html  css  js  c++  java
  • .Net4.0并行库介绍——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有两种方式

    1. 通过构造函数创建 Task t1 = new Task(A);
    2. 通过TaskFactory创建 Task t1 = Task.Factory.StartNew(A);

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

    开始运行Task

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

    等待Task完成

    等待Task完成的也有两种:

    1. 调用Task的成员函数t.Wait()。
    2. 调用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中还有不少非常有用的任务调度和错误处理等的方法和属性,它们使得并发操作变得更为强大和简单,以后会陆续介绍这些知识。

  • 相关阅读:
    HDU 1800 Flying to the Mars 字典树,STL中的map ,哈希树
    字典树 HDU 1075 What Are You Talking About
    字典树 HDU 1251 统计难题
    最小生成树prim算法 POJ2031
    POJ 1287 Networking 最小生成树
    次小生成树 POJ 2728
    最短路N题Tram SPFA
    poj2236 并查集
    POJ 1611并查集
    Number Sequence
  • 原文地址:https://www.cnblogs.com/zjoch/p/3508299.html
Copyright © 2011-2022 走看看