• 多核时代 .NET Framework 4 中的并行编程3任务并行库之Task (下)


    1.     创建可取消操作的Task

    一个任务Task开始之后,我们可以根据需要对任务进行取消,以便停止当前执行的操作.代码如下:

       static void Main(string[] args)

            {

               

                CancellationTokenSource s = new CancellationTokenSource();

                CancellationToken token = s.Token;

                Task task = new Task(() =>

                    {

                        for (int i = 0; i < int.MaxValue; i++)

                        {

                         

                            if (token.IsCancellationRequested)

                            {

                                Console.WriteLine("任务被取消");

                                throw  new  OperationCanceledException(token);

                            }

                            else

                            {

                                Console.WriteLine("当前值 {0}", i);

                            }

                        }

                    }, token);

     

                token.Register(() =>

                {

                    Console.WriteLine("任务取消时执行的委托方法");

                });

     

     

               

                task.Start();

                Console.ReadLine();

     

                Console.WriteLine("取消任务.");

                s.Cancel();

     

                Console.WriteLine("Main执行完毕.");

                Console.ReadLine();

            }

    从上面的代码示例中, 我们可以看到创建可取消任务Task的过程是:先创建一个可取消操作的源CancellationTokenSource的一个对象,然后使用 CancellationTokenSource的可取消操作结构对象CancellationToken,并使用该结构初始化一个任务Task,最后通 过调用可取消操作的源的Cancel()方法,来取消当前关联任务的操作.

    简单的理解, 就是将一个任务Task与可取消操作的源CancellationTokenSource通过CancellationToken关联起来通过 CancellationTokenSource的取消方法来通知相应的任务取消操作.(可以使用某个CancellationToken初始化多个任务 Task,然后在调用CancellationTokenSource的取消方法时,则该多个任务也将被通知取消,从而到达一次取消多个任务的目的)。

    在上面的代码,可以看到:

    Ø token.IsCancellationRequested,它是获取是否已请求取消此标记, 如果此属性为 true,则只能保证已请求取消。 它不保证每个注册的处理程序已完成执行,也不能保证取消请求已完成传播到所有注册的处理程序.也就是说,此属性只是可以得到一个任务ask获取到了取消标记,但它不能代表此任务已经停止完毕或执行完毕取消时注册的事件(token.Register)。

    Ø token.Register(…)向该任务注册一个取消的委托,在任务被取消时,将会执行此委托。

    通过上面的代码,我们应该学会了如何创建一个可以被取消的任务Task,如何判断一个任务Task已经被通知被取消,如何给一个任务Task注册一个取消的处理程序。此外,Task类的IsCanceled属性可以执行任务是否被取消执行完毕。

    2.     Task的等待

    任务Task可以在某些时候去等待某个事件发生或者等待其他任务执行完毕,Task提供了:

    Ø Wait(等待某个事件发生,这就好比:请客吃饭,等一个朋友到来我们就吃饭。)。

    Ø WaitAll(等待某组事件中全部事件都已发生,这就好比:请客吃饭,必须等所有受邀的朋友都到齐才能吃饭)。

    Ø WaitAny(等待某组事件中任何一个事件都已发生,这就好比:请客吃饭,只要所有受邀的朋友中有任何一个朋友,不论是谁,只要有朋友到了,我们就开始吃饭)。

    相应的,这些方法也有很多重载。

    下面来看看具体的代码:

            static void WaitTask()

            {

                CancellationTokenSource ts = new CancellationTokenSource();

                CancellationToken token = ts.Token;

                Task task1 = new Task(() =>

                {

     

                    for (int i = 0; i < 10; i++)

                    {

                        token.ThrowIfCancellationRequested();

                        Console.WriteLine("任务1中i的值是{0}", i);

                        token.WaitHandle.WaitOne(1 * 1000);

                    }

                    Console.WriteLine("任务1执行完毕");

                }, token);

               

                Console.WriteLine("任务1 当前状态:{0}", task1.Status.ToString());

     

                Task task2 = new Task(() =>

                {

                    Console.WriteLine("任务2执行完毕");

                }, token);

     

                task1.Start();

                task2.Start();

                Console.WriteLine("任务1 当前状态:{0}", task1.Status.ToString());

     

                Console.WriteLine("等待所有任务执行完毕…..");

                Task.WaitAll(task1, task2);

        Console.WriteLine("任务1 当前状态:{0}", task1.Status.ToString());

     

                Console.WriteLine("所有任务全部执行完毕.");

                Console.ReadLine();

            }

    需要说明的是:

    Ø 代码token.ThrowIfCancellationRequested();与if(token.IsCancellationRequested) throw new OperationCanceledException(token);是完全等效,只是不同的写法而已。

    Ø 代码token.WaitHandle.WaitOne1*1000)是当前执行该代码的任务Task休息1秒中,类似Threed.Sleep(1*1000)。

    Ø Task.WaitAlltask1,task2….)是等待所有的任务。

    Ø Task Status 获取此任务的 TaskStatus。

    其中TaskStatus枚举有:

    (1)     Created 该任务已初始化,但尚未被计划。 

    (2)     WaitingForActivation 该任务正在等待 .NET Framework 基础结构在内部将其激活并进行计划。 

    (3)     WaitingToRun 该任务已被计划执行,但尚未开始执行。 

    (4)     Running 该任务正在运行,但尚未完成。 

    (5)     WaitingForChildrenToComplete 该任务已完成执行,正在隐式等待附加的子任务完成。 

    (6)     RanToCompletion 已成功完成执行的任务。 

    (7)     Canceled 该任务已通过对其自身的 CancellationToken 引发 OperationCanceledException 对取消进行了确认,此时该标记处于已发送信号状态;或者在该任务开始执行之前,已向该任务的 CancellationToken 发出了信号。 

    (8)     Faulted 由于未处理异常的原因而完成的任务。 

     此外,Task还有以下几个重要属性

    Ø IsCanceled 获取此 Task 实例是否由于被取消的原因而已完成执行。 

    Ø IsCompleted 获取此 Task 是否已完成。 

    Ø IsFaulted 获取 Task 是否由于未经处理异常的原因而完成。 

        好,本节介绍完毕。
     
         本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    原文链接:http://www.cnblogs.com/xray2005/archive/2011/08/22/2148815.html
  • 相关阅读:
    luogu P2015 二叉苹果树
    luogu P1197 [JSOI2008]星球大战
    QBXT T15214 Day2上午遭遇
    luogu P2831 愤怒的小鸟
    luogu P1018 乘积最大
    [BZOJ2402]陶陶的难题II(树链剖分+线段树维护凸包+分数规划)
    [BZOJ1500][NOI2005]维修数列(splay)
    [BZOJ3282]Tree(LCT)
    [BZOJ4785][ZJOI2017]树状数组(概率+二维线段树)
    [BZOJ2427][HAOI2010]软件安装(Tarjan+DP)
  • 原文地址:https://www.cnblogs.com/xwj517537691/p/3127048.html
Copyright © 2020-2023  润新知