• Task


    其实Task跟线程池ThreadPool的功能类似,不过写起来更为简单,直观。代码更简洁了,使用Task来进行操作。可以跟线程一样可以轻松的对执行的方法进行控制。

    顺便提一下,配合CancellationTokenSource类更为可以轻松的对Task操作的代码进行中途终止运行,会在后面的章节中讲述。

    如果我们使用线程池来实现某几个方法运行,然后等待运行完成的大概会编写如下代码:

    1. using (ManualResetEvent m1 = new ManualResetEvent(false))
    2. using (ManualResetEvent m2 = new ManualResetEvent(false))
    3. {
    4.     ThreadPool.QueueUserWorkItem(delegate
    5.     {
    6.         MyMethodA();
    7.         m1.Set();
    8.     });
    9.     ThreadPool.QueueUserWorkItem(delegate
    10.     {
    11.         MyMethodB();
    12.         m2.Set();
    13.     });
    14.     WaitHandle.WaitAll(new WaitHandle[] { m1, m2, });
    15. }

    如果用Task类的话,相对就比较简单了,至少代码看起来很舒服。也就意味着维护也比较方便

    1. Task t1 = Task.Factory.StartNew(delegate { MyMethodA(); });
    2. Task t2 = Task.Factory.StartNew(delegate { MyMethodB(); });
    3. t1.Wait();
    4. t2.Wait();

    上面的方法是一个一个的执行完毕,获取不是我们想要的,我们一般是想要他们一起同时执行,提高程序处理事情的效率。

    1. Task t1 = Task.Factory.StartNew(delegate { MyMethodA(); });
    2. Task t2 = Task.Factory.StartNew(delegate { MyMethodB(); });
    3. Task.WaitAll(t1, t2);

    下面我们来简单介绍下Task的用法

    创建 Task

    创建Task有两种方式,一种是使用构造函数创建,另一种是使用 Task.Factory.StartNew 进行创建。如下代码所示

    1.使用构造函数创建Task

    1.  Task t1 = new Task(MyMethod);

    2.使用Task.Factory.StartNew 进行创建Task

    1.  Task t1 = Task.Factory.StartNew(MyMethod);

    其实这两种方式都是一样的,Task.Factory 是对Task进行管理,调度管理这一类的。好学的伙伴们,可以深入研究。这不是本文的范畴,也许会在后面的文章细说。

    运行 Task

    运行Task的两种方式,在上面我们已经提到过了,一种等待运行完毕,另一种则等待所有运行完毕。不过这里还有一种就是异步运行,跟使用多线程一样,调用Task对象中的Start()方法即可。看看下面这个控制台示例。纯粹是Wait和AllWait的话,仅仅是等待。而不是执行。所以我们还需要调用Start()方法

    1. static void Main(string[] args)
    2. {
    3.     Task t1 = new Task(MyMethod);
    4.     t1.Start();
    5.     Console.WriteLine("主线程代码运行结束");
    6.     Console.ReadLine();
    7. }
    8.  
    9. static void MyMethod()
    10. {
    11.     for (int i = 0; i < 5; i++)
    12.     {
    13.         Console.WriteLine(DateTime.Now.ToString());
    14.         Thread.Sleep(1000);
    15.     }
    16. }

    运行效果如图

    因为我们没有调用Wait 所以是异步执行的~

    取消Task

    我们一开始就描述了 CancellationTokenSource 这个对象对Task的取消运行。一般是用不到这个方法的,一般会正常的退出所运行的代码,如使用 bool IsExit 之类的来进行一个控制。而不是中途强制中断代码。

    可以参考我的这篇文章:http://www.wxzzz.com/643.html

    至于 CancellationTokenSource 控制Task,下一篇文章会进行详细的一个介绍。

    Task的异常处理

    因为Task中是异步执行,你也可以理解为跟多线程一样,具体错误捕获需要自己去捕获。很有意思的是Task的异常还会重新抛到Wait和AllWait中,我们可以进行方便的捕获这些异常。如下代码

    1. static void Main(string[] args)
    2. {
    3.     Task t1 = new Task(MyMethod);
    4.     t1.Start();
    5.     t1.Wait();
    6.     Console.WriteLine("主线程代码运行结束");
    7.     Console.ReadLine();
    8. }
    9.  
    10. static void MyMethod()
    11. {
    12.     throw new Exception("Task异常测试");
    13. }

    运行效果如图

    获取 Task 的返回值

    先看看代码

    1. Task<string> t1 = Task.Factory.StartNew(() => "测试");
    2. t1.Wait();
    3. Console.WriteLine(t1.Result);
    4. Console.ReadLine();

    返回值可以是任意的类型,因为是个泛型嘛~ 还是依然的非常简洁的代码。

  • 相关阅读:
    ROSS仿真系统简单教程
    python小练习1.1
    c语言文件I/O 文件读取和写入
    Python 学习笔记 多线程-threading
    parsec(The parsec benchmark suit )使用教程
    Checkpoint/Restore In Userspace(CRIU)使用细节
    Checkpoint/Restore in Userspace(CRIU)安装和使用
    考研总结
    北理计算机复试经验
    PAT(A) 1075. PAT Judge (25)
  • 原文地址:https://www.cnblogs.com/eedc/p/9153481.html
Copyright © 2020-2023  润新知