Net 4.0 Parallel 编程(六)Task(下)
在之前的文章中已經(jīng)介紹過了Task的基本使用了,以及如何取消任務(wù)、任務(wù)繼續(xù)等功能。本篇Post主要就Task的異常處理以及Wait功能進行些介紹。
等待時間執(zhí)行
在TPL中我們可以通過三種方式進行等待,一是通過CancellTaken的WaitHanle進行等待、第二種則是通過傳統(tǒng)的Tread.Sleep方法、第三種則通過Thread.SpainWait方法。
CancellToken方式:
static void Main(string[] args) {var cancell = new CancellationTokenSource();var token = cancell.Token;var task = new Task(() =>{for (var i = 0; i < 100000; i++){var cancelled = token.WaitHandle.WaitOne(10000);Console.WriteLine(" {0}. Cancelled? {1}",i, cancelled);if (cancelled){throw new OperationCanceledException(token);}}}, token);task.Start();Console.WriteLine("Press enter to cancel token.");Console.ReadLine();cancell.Cancel();Console.WriteLine("Main method complete. Press enter to finish.");Console.ReadLine(); }每次我們等待十秒鐘之后,在進行下次輸出。
上面的功能如果我們要是通過Tread.Sleep方式實現(xiàn):
var task = new Task(() => {for (var i = 0; i < 100000; i++){Thread.Sleep(10000);var cancelled = token.IsCancellationRequested;Console.WriteLine(" {0}. Cancelled? {1}",i, cancelled);if (cancelled){throw new OperationCanceledException(token);}} }, token);Thread.SpainWait則跟上面的種方式完全不同,上面的兩種方式都是會在線程調(diào)度程序不考慮改線程,直等到運行結(jié)束。而Thread.SpainWait的作用實質(zhì)上會將處理器置于十分緊密的循環(huán)中,主要的作用是來實現(xiàn)同步鎖的作用。并不常用,大部分情況下我們可以通過Lock的方式來實現(xiàn)。
等待任務(wù)執(zhí)行
在很多時候我們也許需要等待同時開啟的幾個線程完成之后再來做其他事,在TPL中提供了幾種方式來等待任務(wù)執(zhí)行。Task.Wait等待單個任務(wù)完成;Task.WaitAll等待所有的Task完成、TaskAny等在其中的任何一個或則多個任務(wù)完成。
Task.Wait:
Task.Wait共有5個重載:Wait()、Wait(CancellToken)、Wait(Int32)、Wait(TimeSpan)、Wait(TimeSpan、CancellToken)。各個重載方法的含義:
1)Wait():等待整個任務(wù)完成或則取消或則出現(xiàn)異常;
2)Wait(CancellToken):等待任務(wù)直到CancellToken調(diào)用取消或則完成,或則出現(xiàn)異常;
3)Wait(Int32):等待任務(wù),未完成則到指定的時間;
4)Wait(TimeSpan):同上;
5)Wait(TimeSpan、CancellToken):等待任務(wù)到指定時間,或則CancellToken調(diào)用取消或則任務(wù)完成。
看個示例:
static void Main(string[] args) {var tokenSource = new CancellationTokenSource();CancellationToken token = tokenSource.Token;Task task = createTask(token,6);task.Start();Console.WriteLine("Wait() complete.");task.Wait();Console.WriteLine("Task Completed.");task = createTask(token,3);task.Start();Console.WriteLine("Wait(2) secs for task to complete.");bool completed = task.Wait(2000);Console.WriteLine("Wait ended - task completed: {0}", completed);task = createTask(token,4);task.Start();Console.WriteLine("Wait(2,token) for task to complete.");completed = task.Wait(2000, token);Console.WriteLine("Wait ended - task completed: {0} task cancelled {1}",completed, task.IsCanceled);Console.WriteLine("Main method complete. Press enter to finish.");Console.ReadLine(); } static Task createTask(CancellationToken token,int loop) {return new Task(() =>{for (int i = 0; i < loop; i++){token.ThrowIfCancellationRequested();Console.WriteLine("Task - Int value {0}", i);token.WaitHandle.WaitOne(1000);}}, token); }循環(huán)都會等待1秒鐘,這樣我們可以看看Wait(2000)的效果,看看運行后的效果:
Task.WaitAll
WaitAll方法是等待所有的任務(wù)完成,也有5個重載,我們來看示例:
static void Main(string[] args) {var tokenSource = new CancellationTokenSource();CancellationToken token = tokenSource.Token;var task1 = createTask(token,2);var task2 = createTask(token, 5);task1.Start();task2.Start();Console.WriteLine("Waiting for tasks to complete.");Task.WaitAll(task1, task2);Console.WriteLine("Tasks Completed.");Console.ReadKey(); }其中WaitAll,也可以傳遞時間以及Token參數(shù),進行等待時間以及取消Token的控制。
Task.WaitAny
waitany是等待任何一個任務(wù)完成,完成之后返回其完成的任務(wù)的Index:
static void Main(string[] args) {var tokenSource = new CancellationTokenSource();CancellationToken token = tokenSource.Token;var task1 = createTask(token,2);var task2 = createTask(token, 5);task1.Start();task2.Start();Console.WriteLine("Waiting for tasks to complete.");var index = Task.WaitAny(task1, task2);Console.WriteLine("Tasks Completed.Index is {0}",index);Console.ReadKey(); }異常處理
任何應(yīng)用程序都需要有異常處理機制,在TPL中提供了一套可靠的異常處理機制給我們使用。首先我啊們要知道在哪些環(huán)節(jié)會觸發(fā)異常,在TPL中,異常的觸發(fā)器主要是這幾個:
Task.Wait(), Task.WaitAll(), Task,WaitAny(),Task.Result。而在TPL出現(xiàn)的異常都會以AggregateException的示例拋出,我們在進行基本的異常處理時,可以通過查看AggregateException的InnerExceptions來進行內(nèi)部異常的捕獲:
static void Main(string[] args) {var tokenSource = new CancellationTokenSource();var token = tokenSource.Token;var task1 = new Task(() =>{throw new NullReferenceException() { Source="task1"};});var task2 = new Task(() =>{throw new ArgumentNullException("a", "a para can not be null") { Source="task2"};});var task3 = new Task(() =>{throw new DivideByZeroException("Can not be zero") { Source = "task3" };});var task4 = new Task(() =>{Console.WriteLine("Task4 .");});task1.Start(); task2.Start(); task3.Start(); task4.Start();try{Task.WaitAll(task1, task2, task3, task4);}catch(AggregateException ex){foreach (Exception inner in ex.InnerExceptions){Console.WriteLine("Exception type {0} from {1}",inner.GetType(), inner.Source);}}Console.ReadLine(); }上面的例子中通過便利AggregateException的InnerException進行詳細異常的處理,效果:
同時,我們還可以通過Task的幾個屬性來判斷Task的狀態(tài),如:IsCompleted, IsFaulted, IsCancelled,Exception。另外,AggregateException中還提供了
Handle方法來給我們方法來給我們處理每個內(nèi)部 異常,每個異常發(fā)生時都會調(diào)用Handle傳入的delegate ,同時我們需要通過返回True,False來告訴異常是否已經(jīng)被處理,比如對于OperationCanceledException我們知道是取消了Task,是肯定可以處理的:
?
try{Task.WaitAll(task1, task2, task3, task4);}catch(AggregateException ex){ex.Handle((e) =>{if (e is OperationCanceledException){return true;}else{return false;}});}總結(jié)
本篇Post中,我們主要學(xué)習(xí)了Wait 、Wait for task以及異常的處理,希望對您有用。(PS:好長時間不寫B(tài)log了,之間間隔了好幾個月。)
作者:Henllyee Cui出處: http://henllyee.cnblogs.com/
本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明。
轉(zhuǎn)載于:https://www.cnblogs.com/dajiang02/archive/2012/02/10/2344843.html
總結(jié)
以上是生活随笔為你收集整理的Net 4.0 Parallel 编程(六)Task(下)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 推荐8个优秀的基于HTML5的信息图
- 下一篇: 用于读、写、删除、比较Session中的