天天看點

多核時代 .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 = newCancellationTokenSource();

            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執行完畢");

            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.WaitOne(1*1000)是目前執行該代碼的任務Task休息1秒中,類似Threed.Sleep(1*1000)。

Ø Task.WaitAll(task1,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,如需轉載請自行聯系原作者

繼續閱讀