• Task.WaitAll代替WaitHandle.WaitAll


    Task.Waitall阻塞了当前线程直到全完。whenall开启个新监控线程去判读括号里的所有线程执行情况并立即返回,等都完成了就退出监控线程并返回监控数据。

    task.Result会等待异步方法返回,当然阻塞住了。别和await 同时用。

    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);

     
     
  • 相关阅读:
    MFC中小笔记(四)
    MFC中小笔记(三)
    MFC中小笔记
    关于小蜘蛛诞生的坎坎坷坷
    Win32Api程序设计 常用域改变(设定)窗口位置、大小的api
    Win32Api程序设计 注册窗口类
    TCP segment of a reassembled PDU【转】
    计算机网络复习 -- 概念梳理
    指针(pointer) -- (上)
    原来我连真正的调试都不会,每次都是靠编译器(⊙﹏⊙)b
  • 原文地址:https://www.cnblogs.com/x-poior/p/7112645.html
Copyright © 2020-2023  润新知