日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線(xiàn)溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
.NET4并行編程入門(mén)之Task執(zhí)行和異常處理

查看本系列其他文章,請(qǐng)參看

創(chuàng)新互聯(lián)是一家專(zhuān)業(yè)提供永年企業(yè)網(wǎng)站建設(shè),專(zhuān)注與成都網(wǎng)站制作、網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè)H5響應(yīng)式網(wǎng)站、小程序制作等業(yè)務(wù)。10年已為永年眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專(zhuān)業(yè)網(wǎng)絡(luò)公司優(yōu)惠進(jìn)行中。

[[11782]]

本篇主要講述等待task執(zhí)行完成。

本篇的議題如下:

1. 等待Task執(zhí)行完成

2. Task中的異常處理

首先注意一點(diǎn):這里提到的"等待"和之前文章提到的"休眠"意思是不一樣的:

等待:在等待一個(gè)task的時(shí)候,這個(gè)task還是在運(yùn)行之中的,"等待"相當(dāng)于在監(jiān)聽(tīng)運(yùn)行的task的執(zhí)行情況。

休眠:讓tasku不運(yùn)行。

在上篇文章中介紹了如果從Task中獲取執(zhí)行后的結(jié)果:在Task執(zhí)行完成之后調(diào)用Task.Result獲取。其實(shí)也可以用其他的方法等待Task執(zhí)行完成而不獲取結(jié)果,這是很有用的:如果你想等待一個(gè)task完成之后再去做其他的事情。而且我們還可以等待一個(gè)task執(zhí)行完成,或者等待所有的task執(zhí)行完成,或者等待很多task中的一個(gè)執(zhí)行完成。因?yàn)門(mén)ask是由內(nèi)部的Scheduler管理的,調(diào)用wait方法,其實(shí)就是我們?cè)诒O(jiān)控task的執(zhí)行,看看這個(gè)task是否執(zhí)行完了,如果完成,那么wanit方法就返回true,反之。

1. 等待Task執(zhí)行完成

1.1等待單獨(dú)的一個(gè)Task執(zhí)行完成

我們可以用Wait()方法來(lái)一直等待一個(gè)Task執(zhí)行完成。當(dāng)task執(zhí)行完成,或者被cancel,或者拋出異常,這個(gè)方法才會(huì)返回??梢允褂肳ait()方法的不同重載。舉個(gè)例子:

代碼

 
 
 
  1. static void Main(string[] args)  
  2.     {  
  3.         // create the cancellation token source  
  4.         CancellationTokenSource tokenSource = new CancellationTokenSource();  
  5.         // create the cancellation token  
  6.         CancellationToken token = tokenSource.Token;  
  7.         // create and start the first task, which we will let run fully  
  8.         Task task = createTask(token);  
  9.         task.Start();  
  10.  
  11.         // wait for the task  
  12.         Console.WriteLine("Waiting for task to complete.");  
  13.         task.Wait();  
  14.         Console.WriteLine("Task Completed.");  
  15.  
  16.         // create and start another task  
  17.         task = createTask(token);  
  18.         task.Start();  
  19.         Console.WriteLine("Waiting 2 secs for task to complete.");  
  20.         bool completed = task.Wait(2000);  
  21.         Console.WriteLine("Wait ended - task completed: {0}", completed);  
  22.  
  23.         // create and start another task  
  24.         task = createTask(token);  
  25.         task.Start();  
  26.         Console.WriteLine("Waiting 2 secs for task to complete.");  
  27.         completed = task.Wait(2000, token);  
  28.         Console.WriteLine("Wait ended - task completed: {0} task cancelled {1}",  
  29.         completed, task.IsCanceled);  
  30.  
  31.         // wait for input before exiting  
  32.         Console.WriteLine("Main method complete. Press enter to finish.");  
  33.         Console.ReadLine();  
  34.     }  
  35.  
  36.     static Task createTask(CancellationToken token)  
  37.     {  
  38.         return new Task(() =>  
  39.         {  
  40.             for (int i = 0; i < 5; i++)  
  41.             {  
  42.                 // check for task cancellation  
  43.                 token.ThrowIfCancellationRequested();  
  44.                 // print out a message  
  45.                 Console.WriteLine("Task - Int value {0}", i);  
  46.                 // put the task to sleep for 1 second  
  47.                 token.WaitHandle.WaitOne(1000);  
  48.             }  
  49.         }, token);  
  50.     } 

從上面的例子可以看出,wait方法子task執(zhí)行完成之后會(huì)返回true。

注意:當(dāng)在執(zhí)行的task內(nèi)部拋出了異常之后,這個(gè)異常在調(diào)用wait方法時(shí)會(huì)被再次拋出。后面再"異常處理篇"會(huì)講述。

1.2.等待多個(gè)task

我們也可以用WaitAll()方法來(lái)一直到等待多個(gè)task執(zhí)行完成。只有當(dāng)所有的task執(zhí)行完成,或者被cancel,或者拋出異常,這個(gè)方法才會(huì)返回。WiatAll()方法和Wait()方法一樣有一些重載。

注意:如果在等在的多個(gè)task之中,有一個(gè)task拋出了異常,那么調(diào)用WaitAll()方法時(shí)就會(huì)拋出異常。

代碼

 
 
 
  1. static void Main(string[] args)  
  2.     {  
  3.         // create the cancellation token source  
  4.         CancellationTokenSource tokenSource = new CancellationTokenSource();  
  5.         // create the cancellation token  
  6.         CancellationToken token = tokenSource.Token;  
  7.         // create the tasks  
  8.         Task task1 = new Task(() =>  
  9.         {  
  10.             for (int i = 0; i < 5; i++)  
  11.             {  
  12.                 // check for task cancellation  
  13.                 token.ThrowIfCancellationRequested();  
  14.                 // print out a message  
  15.                 Console.WriteLine("Task 1 - Int value {0}", i);  
  16.                 // put the task to sleep for 1 second  
  17.                 token.WaitHandle.WaitOne(1000);  
  18.             }  
  19.             Console.WriteLine("Task 1 complete");  
  20.         }, token);  
  21.         Task task2 = new Task(() =>  
  22.         {  
  23.             Console.WriteLine("Task 2 complete");  
  24.         }, token);  
  25.  
  26.         // start the tasks  
  27.         task1.Start();  
  28.         task2.Start();  
  29.         // wait for the tasks  
  30.         Console.WriteLine("Waiting for tasks to complete.");  
  31.         Task.WaitAll(task1, task2);  
  32.         Console.WriteLine("Tasks Completed.");  
  33.         // wait for input before exiting  
  34.         Console.WriteLine("Main method complete. Press enter to finish.");  
  35.         Console.ReadLine();  
  36.     } 

 在上面的例子中,首先創(chuàng)建了兩個(gè)task,注意我們創(chuàng)建的是可以被cancel的task,因?yàn)槭褂肅ancellationToken。而且在***個(gè)task中還是用waitOne()休眠方法,其實(shí)目的很簡(jiǎn)單:使得這個(gè)task的運(yùn)行時(shí)間長(zhǎng)一點(diǎn)而已。之后我們就調(diào)用了WaitAll()方法,這個(gè)方法一直到兩個(gè)task執(zhí)行完成之后才會(huì)返回的。

1.3.等待多個(gè)task中的一個(gè)task執(zhí)行完成

可以用WaitAny()方法來(lái)等待多個(gè)task中的一個(gè)task執(zhí)行完成。通俗的講就是:有很多的task在運(yùn)行,調(diào)用了WaitAny()方法之后,只要那些運(yùn)行的task其中有一個(gè)運(yùn)行完成了,那么WaitAny()就返回了。

代碼

 
 
 
  1. static void Main(string[] args)  
  2.     {  
  3.         // create the cancellation token source  
  4.         CancellationTokenSource tokenSource = new CancellationTokenSource();  
  5.         // create the cancellation token  
  6.         CancellationToken token = tokenSource.Token;  
  7.         // create the tasks  
  8.         Task task1 = new Task(() =>  
  9.         {  
  10.             for (int i = 0; i < 5; i++)  
  11.             {  
  12.                 // check for task cancellation  
  13.                 token.ThrowIfCancellationRequested();  
  14.                 // print out a message  
  15.                 Console.WriteLine("Task 1 - Int value {0}", i);  
  16.                 // put the task to sleep for 1 second  
  17.                 token.WaitHandle.WaitOne(1000);  
  18.             }  
  19.             Console.WriteLine("Task 1 complete");  
  20.         }, token);  
  21.         Task task2 = new Task(() =>  
  22.         {  
  23.             Console.WriteLine("Task 2 complete");  
  24.         }, token);  
  25.  
  26.         // start the tasks  
  27.         task1.Start();  
  28.         task2.Start();  
  29.         // wait for the tasks  
  30.         Console.WriteLine("Waiting for tasks to complete.");  
  31.         Task.WaitAll(task1, task2);  
  32.         Console.WriteLine("Tasks Completed.");  
  33.         // wait for input before exiting  
  34.         Console.WriteLine("Main method complete. Press enter to finish.");  
  35.         Console.ReadLine();  
  36.     } 

2. Task中的異常處理

在并行編程(TPL)中另外一個(gè)已經(jīng)標(biāo)準(zhǔn)化了的操作就是"異常處理"。而且在并行編程中異常處理顯得尤為重要,因?yàn)椴⑿芯幊虝r(shí)與系統(tǒng)中的線(xiàn)程相關(guān)的,出了異常,你開(kāi)發(fā)的程序就很有可能崩潰。

下面就詳細(xì)介紹TPL中異常處理操作。

 a.處理基本的異常。

 在操作task的時(shí)候,只要出現(xiàn)了異常,.NET Framework就會(huì)把這些異常記錄下來(lái)。例如在執(zhí)行Task.Wait(),Task.WaitAll(),Task.WaitAny(),Task.Result.不管那里出現(xiàn)了異常,***拋出的就是一個(gè)System.AggregateException.

 System.AggregateException時(shí)用來(lái)包裝一個(gè)或者多個(gè)異常的,這個(gè)類(lèi)時(shí)很有用的,特別是在調(diào)用Task.WaitAll()方法時(shí)。因?yàn)樵赥ask.WaitAll()是等待多個(gè)task執(zhí)行完成,如果有任意task執(zhí)行出了異常,那么這個(gè)異常就會(huì)被記錄在System.AggregateException中,不同的task可能拋出的異常不同,但是這些異常都會(huì)被記錄下來(lái)。

下面就是給出一個(gè)例子:在例子中,創(chuàng)建了兩個(gè)task,它們都拋出異常。然后主線(xiàn)程開(kāi)始運(yùn)行task,并且調(diào)用WaitAll()方法,然后就捕獲拋出的System.AggregateException,顯示詳細(xì)信息。

代碼

 
 
 
  1. static void Main(string[] args)  
  2.     {  
  3.  
  4.         // create the tasks  
  5.         Task task1 = new Task(() =>  
  6.         {  
  7.             ArgumentOutOfRangeException exception = new ArgumentOutOfRangeException();  
  8.             exception.Source = "task1";  
  9.             throw exception;  
  10.         });  
  11.         Task task2 = new Task(() =>  
  12.         {  
  13.             throw new NullReferenceException();  
  14.         });  
  15.         Task task3 = new Task(() =>  
  16.         {  
  17.             Console.WriteLine("Hello from Task 3");  
  18.         });  
  19.         // start the tasks  
  20.         task1.Start(); task2.Start(); task3.Start();  
  21.         // wait for all of the tasks to complete  
  22.         // and wrap the method in a try...catch block  
  23.         try 
  24.         {  
  25.             Task.WaitAll(task1, task2, task3);  
  26.         }  
  27.         catch (AggregateException ex)  
  28.         {  
  29.             // enumerate the exceptions that have been aggregated  
  30.             foreach (Exception inner in ex.InnerExceptions)  
  31.             {  
  32.                 Console.WriteLine("Exception type {0} from {1}",  
  33.                 inner.GetType(), inner.Source);  
  34.             }  
  35.         }  
  36.         // wait for input before exiting  
  37.         Console.WriteLine("Main method complete. Press enter to finish.");  
  38.         Console.ReadLine();  
  39.     } 

 

 從上面的例子可以看出,為了獲得被包裝起來(lái)的異常,需要調(diào)用System.AggregateException的InnerExceptions屬性,這個(gè)屬性返回一個(gè)異常的集合,然后就可以遍歷這個(gè)集合。

而且從上面的例子可以看到:Exeception.Source屬性被用來(lái)指明task1的異常時(shí)ArgumentOutRangeException.

 b.使用迭代的異常處理Handler

 一般情況下,我們需要區(qū)分哪些異常需要處理,而哪些異常需要繼續(xù)往上傳遞。AggregateException類(lèi)提供了一個(gè)Handle()方法,我們可以用這個(gè)方法來(lái)處理

AggregateException中的每一個(gè)異常。在這個(gè)Handle()方法中,返回true就表明,這個(gè)異常我們已經(jīng)處理了,不用拋出,反之。

 在下面的例子中,拋出了一個(gè)OperationCancelException,在之前的task的取消一文中,已經(jīng)提到過(guò):當(dāng)在task中拋出這個(gè)異常的時(shí)候,實(shí)際上就是這個(gè)task發(fā)送了取消的請(qǐng)求。下面的代碼中,描述了如果在AggregateException.Handle()中處理不同的異常。

代碼

 
 
 
  1. static void Main(string[] args)  
  2.     {  
  3.         // create the cancellation token source and the token  
  4.         CancellationTokenSource tokenSource = new CancellationTokenSource();  
  5.         CancellationToken token = tokenSource.Token;  
  6.         // create a task that waits on the cancellation token  
  7.         Task task1 = new Task(() =>  
  8.         {  
  9.             // wait forever or until the token is cancelled  
  10.             token.WaitHandle.WaitOne(-1);  
  11.             // throw an exception to acknowledge the cancellation  
  12.             throw new OperationCanceledException(token);  
  13.         }, token);  
  14.         // create a task that throws an exception  
  15.         Task task2 = new Task(() =>  
  16.         {  
  17.             throw new NullReferenceException();  
  18.         });  
  19.         // start the tasks  
  20.         task1.Start(); task2.Start();  
  21.         // cancel the token  
  22.         tokenSource.Cancel();  
  23.         // wait on the tasks and catch any exceptions  
  24.         try 
  25.         {  
  26.             Task.WaitAll(task1, task2);  
  27.         }  
  28.         catch (AggregateException ex)  
  29.         {  
  30.             // iterate through the inner exceptions using  
  31.             // the handle method  
  32.             ex.Handle((inner) =>  
  33.             {  
  34.                 if (inner is OperationCanceledException)  
  35.                 {  
  36.  
  37.                     // ...handle task cancellation...  
  38.                     return true;  
  39.                 }  
  40.                 else 
  41.                 {  
  42.                     // this is an exception we don't know how  
  43.                     // to handle, so return false  
  44.                     return false;  
  45.                 }  
  46.             });  
  47.         }  
  48.         // wait for input before exiting  
  49.         Console.WriteLine("Main method complete. Press enter to finish.");  
  50.         Console.ReadLine();  
  51.     } 

 今天就寫(xiě)到這里。謝謝!


分享題目:.NET4并行編程入門(mén)之Task執(zhí)行和異常處理
轉(zhuǎn)載來(lái)于:http://www.5511xx.com/article/cddssgi.html