偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

.NET 4并行編程入門之Task的取消

開發(fā) 后端
本文將介紹的是.NET 4并行編程入門,將談到的問題包括通過輪詢的方式檢測(cè)Task是否被取消,用委托delegate來檢測(cè)Task是否被取消,用Wait Handle還檢測(cè)Task是否被取消和取消多個(gè)Task。

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

[[11687]]

因?yàn)門ask是.NET 4并行編程最為核心的一個(gè)類,也我們?cè)谑窃诓⑿芯幊坛34蚪坏赖念?,所以,?duì)Task對(duì)全面的了解很有必要。

上篇文章主要講述了如何創(chuàng)建一個(gè)task,本篇文章主要講述如何取消一個(gè)task。

本篇主的主要議題如下:

1. 通過輪詢的方式檢測(cè)Task是否被取消

2.  用委托delegate來檢測(cè)Task是否被取消

3. 用Wait Handle還檢測(cè)Task是否被取消

4. 取消多個(gè)Task

5. 創(chuàng)建組合的取消Task的Token

6. 判斷一個(gè)Task是否已經(jīng)被取消了

本篇的理論不多,代碼的例子很多。

在TPL中一個(gè)標(biāo)準(zhǔn)化的操作就是”取消Task”。之所以說它是個(gè)標(biāo)準(zhǔn)化的操作,其實(shí)是把這個(gè)操作和之前傳統(tǒng)的多線程編程進(jìn)行比較而言的。

在之前的多線程編程中,我們一般是自己寫一些代碼來取消線程的運(yùn)行。但是在.NET 4的TPL中就內(nèi)置了取消的方法,可能我們覺得TPL沒有必要內(nèi)置這些代碼,因?yàn)樘?jiǎn)單了。但是這個(gè)內(nèi)置的方法不僅僅只是取消了運(yùn)行的Task,而且還減小了在取消運(yùn)行的Task時(shí)可能產(chǎn)生的一些風(fēng)險(xiǎn),我們后續(xù)文章會(huì)詳細(xì)講述。

創(chuàng)建一個(gè)取消的Task一般要進(jìn)行下面一些步驟:

a.創(chuàng)建System.Threading.CancellationTokenSource的一個(gè)實(shí)例:

  1. // create the cancellation token source  
  2. ancellationTokenSource tokenSource = new CancellationTokenSource(); 

b.通過CancellationTokenSource.Token屬性獲得一個(gè)System.Threading.CancellationToken:

  1. CancellationToken token = tokenSource.Token; 

c.創(chuàng)建一個(gè)新的Task或者Task<T>,并且在構(gòu)造函數(shù)傳入Action或者Action<object>的委托作為***個(gè)參數(shù),傳入CancellationToken作為第二個(gè)參數(shù):

  1. Task task = new Task(new Action(printMessage), token); 

d.調(diào)用Task的Start()方法。

上面的步驟和我們之前介紹的創(chuàng)建一個(gè)Task的代碼幾乎一樣,只是在構(gòu)造函數(shù)中多傳入了一個(gè)參數(shù)。

如果想要取消一個(gè)Task的運(yùn)行,只要調(diào)用CancellationToken實(shí)例的Cancel()方法就可以了。

有點(diǎn)要特別注意的,當(dāng)我們調(diào)用了Cancel()方法之后,.NET Framework不會(huì)強(qiáng)制性的去關(guān)閉運(yùn)行的Task。

我們自己必須去檢測(cè)之前在創(chuàng)建Task時(shí)候傳入的那個(gè)CancellationToken。

我們?cè)趧?chuàng)建Task是傳入CancellationToken到構(gòu)造函數(shù),其實(shí)這個(gè)CancellationToken就是.NET Framework用來避免我們?cè)俅芜\(yùn)行已經(jīng)被取消的Task,可以說就是一個(gè)標(biāo)志位。

首先,進(jìn)入***個(gè)議題:

1.通過輪詢的方式檢測(cè)Task是否被取消

在很多Task內(nèi)部都包含了循環(huán),用來處理數(shù)據(jù)。我們可以在循環(huán)中通過CancellationToken的IsCancellationRequest屬性來檢測(cè)task是否被取消了。如果這個(gè)屬性為true,那么我們就得跳出循環(huán),并且釋放task所占用的資源(如數(shù)據(jù)庫資源,文件資源等).

我們也可以在task運(yùn)行體中拋出System.Threading.OperationCanceledException來取消運(yùn)行的task。

代碼如下:

代碼 

  1. while (true)  
  2. {  
  3.     if (token.IsCancellationRequested)  
  4.     {  
  5.           // tidy up and release resources  
  6.            throw new OperationCanceledException(token);  
  7.     }  
  8.      else 
  9.      {  
  10.         // do a unit of work  
  11.        }  
  12.  } 

如果我們沒有任何的資源要釋放,那么只要簡(jiǎn)單的調(diào)用CancellationToken.ThrowIfCancellationRequested()方法,這個(gè)方法會(huì)檢查是否要取消task,并且拋出異常。代碼如下:

  1. while (true)  
  2.  
  3.        token.ThrowIfCancellationRequested();  
  4.         // do a unit of work  

下面就給出有一個(gè)完整的例子:創(chuàng)建一個(gè)可以取消的task,并且通過輪詢不斷的檢查是否要取消task

代碼如下:

代碼        

  1. static void Main(string[] args)  
  2.         {  
  3.             // create the cancellation token source  
  4.             CancellationTokenSource tokenSource = new CancellationTokenSource();  
  5.  
  6.             // create the cancellation token  
  7.             CancellationToken token = tokenSource.Token;  
  8.             // create the task  
  9.  
  10.             Task task = new Task(() =>  
  11.             {  
  12.                 for (int i = 0; i < int.MaxValue; i++)  
  13.                 {  
  14.                     if (token.IsCancellationRequested)  
  15.                     {  
  16.                         Console.WriteLine("Task cancel detected");  
  17.                         throw new OperationCanceledException(token);  
  18.                     }  
  19.                     else 
  20.                     {  
  21.                         Console.WriteLine("Int value {0}", i);  
  22.                     }  
  23.                 }  
  24.             }, token);  
  25.  
  26.             // wait for input before we start the task  
  27.             Console.WriteLine("Press enter to start task");  
  28.             Console.WriteLine("Press enter again to cancel task");  
  29.             Console.ReadLine();  
  30.  
  31.             // start the task  
  32.             task.Start();  
  33.  
  34.             // read a line from the console.  
  35.             Console.ReadLine();  
  36.  
  37.             // cancel the task  
  38.             Console.WriteLine("Cancelling task");  
  39.             tokenSource.Cancel();  
  40.  
  41.             // wait for input before exiting  
  42.             Console.WriteLine("Main method complete. Press enter to finish.");  
  43.             Console.ReadLine();  
  44.         } 

2.       用委托delegate來檢測(cè)Task是否被取消

我們可以在注冊(cè)一個(gè)委托到CancellationToken中,這個(gè)委托的方法在CancellationToken.Cancel()調(diào)用之前被調(diào)用。

我們可以用這個(gè)委托中的方法來作為一個(gè)檢測(cè)task是否被取消的另外一個(gè)可選的方法,因?yàn)檫@個(gè)方法是在Cancel()方法被調(diào)用之前就調(diào)用的,所以這個(gè)委托中的方法可以檢測(cè)task是否被cancel了,也就是說,只要這個(gè)委托的方法被調(diào)用,那么就說這個(gè)CancellationToken.Cancel()方法被調(diào)用了,而且在這個(gè)委托的方法中我們可以做很多的事情,如通知用戶取消操作發(fā)生了。

下面的代碼給出了一個(gè)例子。

代碼        

  1. static void Main(string[] args)  
  2.         {  
  3.             // create the cancellation token source  
  4.             CancellationTokenSource tokenSource = new CancellationTokenSource();  
  5.  
  6.             // create the cancellation token  
  7.             CancellationToken token = tokenSource.Token;  
  8.  
  9.             // create the task  
  10.             Task task = new Task(() =>  
  11.             {  
  12.                 for (int i = 0; i < int.MaxValue; i++)  
  13.                 {  
  14.                     if (token.IsCancellationRequested)  
  15.                     {  
  16.                         Console.WriteLine("Task cancel detected");  
  17.                         throw new OperationCanceledException(token);  
  18.                     }  
  19.                     else 
  20.                     {  
  21.                         Console.WriteLine("Int value {0}", i);  
  22.                     }  
  23.                 }  
  24.             }, token);  
  25.  
  26.             // register a cancellation delegate  
  27.             token.Register(() =>  
  28.             {  
  29.                 Console.WriteLine(">>>>>> Delegate Invoked\n");  
  30.             });  
  31.  
  32.             // wait for input before we start the task  
  33.             Console.WriteLine("Press enter to start task");  
  34.             Console.WriteLine("Press enter again to cancel task");  
  35.             Console.ReadLine();  
  36.  
  37.             // start the task  
  38.             task.Start();  
  39.             // read a line from the console.  
  40.             Console.ReadLine();  
  41.  
  42.             // cancel the task  
  43.             Console.WriteLine("Cancelling task");  
  44.             tokenSource.Cancel();  
  45.  
  46.             // wait for input before exiting  
  47.             Console.WriteLine("Main method complete. Press enter to finish.");  
  48.             Console.ReadLine();  
  49.         } 

3.       用Wait Handle還檢測(cè)Task是否被取消

第三種方法檢測(cè)task是否被cancel就是調(diào)用CancellationToken.WaitHandle屬性。對(duì)于這個(gè)屬性的詳細(xì)使用,在后續(xù)的文章中會(huì)深入的講述,在這里主要知道一點(diǎn)就行了:CancellationToken的WaitOne()方法會(huì)阻止task的運(yùn)行,只有CancellationToken的cancel()方法被調(diào)用后,這種阻止才會(huì)釋放。

在下面的例子中,創(chuàng)建了兩個(gè)task,其中task2調(diào)用了WaitOne()方法,所以task2一直不會(huì)運(yùn)行,除非調(diào)用了CancellationToken的Cancel()方法,所以WaitOne()方法也算是檢測(cè)task是否被cancel的一種方法了。

代碼        

  1. static void Main(string[] args)  
  2.        {  
  3.  
  4.            // create the cancellation token source  
  5.            CancellationTokenSource tokenSource = new CancellationTokenSource();  
  6.  
  7.            // create the cancellation token  
  8.            CancellationToken token = tokenSource.Token;  
  9.  
  10.            // create the task  
  11.            Task task1 = new Task(() =>  
  12.            {  
  13.                for (int i = 0; i < int.MaxValue; i++)  
  14.                {  
  15.                    if (token.IsCancellationRequested)  
  16.                    {  
  17.                        Console.WriteLine("Task cancel detected");  
  18.                        throw new OperationCanceledException(token);  
  19.                    }  
  20.                    else 
  21.                    {  
  22.                        Console.WriteLine("Int value {0}", i);  
  23.                    }  
  24.                }  
  25.            }, token);  
  26.  
  27.            // create a second task that will use the wait handle  
  28.            Task task2 = new Task(() =>  
  29.            {  
  30.                // wait on the handle  
  31.                token.WaitHandle.WaitOne();  
  32.                // write out a message  
  33.                Console.WriteLine(">>>>> Wait handle released");  
  34.            });  
  35.  
  36.            // wait for input before we start the task  
  37.            Console.WriteLine("Press enter to start task");  
  38.            Console.WriteLine("Press enter again to cancel task");  
  39.            Console.ReadLine();  
  40.            // start the tasks  
  41.            task1.Start();  
  42.            task2.Start();  
  43.  
  44.            // read a line from the console.  
  45.            Console.ReadLine();  
  46.  
  47.            // cancel the task  
  48.            Console.WriteLine("Cancelling task");  
  49.            tokenSource.Cancel();  
  50.  
  51.            // wait for input before exiting  
  52.            Console.WriteLine("Main method complete. Press enter to finish.");  
  53.            Console.ReadLine();  
  54.        } 

4.      取消多個(gè)Task

我們可以使用一個(gè)CancellationToken來創(chuàng)建多個(gè)不同的Tasks,當(dāng)這個(gè)CancellationToken的Cancel()方法調(diào)用的時(shí)候,使用了這個(gè)token的多個(gè)task都會(huì)被取消。

代碼        

  1. static void Main(string[] args)  
  2.         {  
  3.             // create the cancellation token source  
  4.             CancellationTokenSource tokenSource = new CancellationTokenSource();  
  5.  
  6.             // create the cancellation token  
  7.             CancellationToken token = tokenSource.Token;  
  8.  
  9.             // create the tasks  
  10.             Task task1 = new Task(() =>  
  11.             {  
  12.                 for (int i = 0; i < int.MaxValue; i++)  
  13.                 {  
  14.                     token.ThrowIfCancellationRequested();  
  15.                     Console.WriteLine("Task 1 - Int value {0}", i);  
  16.                 }  
  17.             }, token);  
  18.  
  19.             Task task2 = new Task(() =>  
  20.             {  
  21.                 for (int i = 0; i < int.MaxValue; i++)  
  22.                 {  
  23.                     token.ThrowIfCancellationRequested();  
  24.                     Console.WriteLine("Task 2 - Int value {0}", i);  
  25.                 }  
  26.             }, token);  
  27.             // wait for input before we start the tasks  
  28.             Console.WriteLine("Press enter to start tasks");  
  29.             Console.WriteLine("Press enter again to cancel tasks");  
  30.             Console.ReadLine();  
  31.  
  32.             // start the tasks  
  33.             task1.Start();  
  34.             task2.Start();  
  35.  
  36.             // read a line from the console.  
  37.             Console.ReadLine();  
  38.  
  39.             // cancel the task  
  40.             Console.WriteLine("Cancelling tasks");  
  41.             tokenSource.Cancel();  
  42.             // wait for input before exiting  
  43.             Console.WriteLine("Main method complete. Press enter to finish.");  
  44.             Console.ReadLine();  
  45.         } 

5. 創(chuàng)建組合的取消Task的Token

我們可以用CancellationTokenSource.CreateLinkedTokenSource()方法來創(chuàng)建一個(gè)組合的token,這個(gè)組合的token有很多的CancellationToken組成。主要組合token中的任意一個(gè)token調(diào)用了Cancel()方法,那么使用這個(gè)組合token的所有task就會(huì)被取消。代碼如下:

代碼        

  1. static void Main(string[] args)  
  2.        {  
  3.            // create the cancellation token sources  
  4.            CancellationTokenSource tokenSource1 = new CancellationTokenSource();  
  5.            CancellationTokenSource tokenSource2 = new CancellationTokenSource();  
  6.            CancellationTokenSource tokenSource3 = new CancellationTokenSource();  
  7.  
  8.            // create a composite token source using multiple tokens  
  9.            CancellationTokenSource compositeSource =   
  10.                CancellationTokenSource.CreateLinkedTokenSource(  
  11.            tokenSource1.Token, tokenSource2.Token, tokenSource3.Token);  
  12.  
  13.            // create a cancellable task using the composite token  
  14.            Task task = new Task(() =>  
  15.            {  
  16.                // wait until the token has been cancelled  
  17.                compositeSource.Token.WaitHandle.WaitOne();  
  18.                // throw a cancellation exception  
  19.                throw new OperationCanceledException(compositeSource.Token);  
  20.            }, compositeSource.Token);  
  21.  
  22.            // start the task  
  23.            task.Start();  
  24.  
  25.            // cancel one of the original tokens  
  26.            tokenSource2.Cancel();  
  27.  
  28.            // wait for input before exiting  
  29.            Console.WriteLine("Main method complete. Press enter to finish.");  
  30.            Console.ReadLine();  
  31.        } 

6.      判斷一個(gè)Task是否已經(jīng)被取消了

可以使用Task的IsCancelled屬性來判斷task是否被取消了。代碼如下:

代碼        

  1. static void Main(string[] args)  
  2.        {  
  3.            // create the cancellation token source  
  4.            CancellationTokenSource tokenSource1 = new CancellationTokenSource();  
  5.  
  6.            // create the cancellation token  
  7.            CancellationToken token1 = tokenSource1.Token;  
  8.  
  9.            // create the first task, which we will let run fully  
  10.            Task task1 = new Task(() =>  
  11.            {  
  12.                for (int i = 0; i < 10; i++)  
  13.                {  
  14.                    token1.ThrowIfCancellationRequested();  
  15.                    Console.WriteLine("Task 1 - Int value {0}", i);  
  16.                }  
  17.            }, token1);  
  18.  
  19.            // create the second cancellation token source  
  20.            CancellationTokenSource tokenSource2 = new CancellationTokenSource();  
  21.  
  22.            // create the cancellation token  
  23.            CancellationToken token2 = tokenSource2.Token;  
  24.  
  25.            // create the second task, which we will cancel  
  26.            Task task2 = new Task(() =>  
  27.            {  
  28.                for (int i = 0; i < int.MaxValue; i++)  
  29.                {  
  30.                    token2.ThrowIfCancellationRequested();  
  31.                    Console.WriteLine("Task 2 - Int value {0}", i);  
  32.                }  
  33.            }, token2);  
  34.  
  35.            // start all of the tasks  
  36.            task1.Start();  
  37.            task2.Start();  
  38.  
  39.            // cancel the second token source  
  40.            tokenSource2.Cancel();  
  41.            // write out the cancellation detail of each task  
  42.            Console.WriteLine("Task 1 cancelled? {0}", task1.IsCanceled);  
  43.            Console.WriteLine("Task 2 cancelled? {0}", task2.IsCanceled);  
  44.            // wait for input before exiting  
  45.            Console.WriteLine("Main method complete. Press enter to finish.");  
  46.            Console.ReadLine();  
  47.        } 

原文標(biāo)題:.NET 4 并行(多核)編程系列之三 

鏈接:http://www.cnblogs.com/Leo_wl/archive/2010/06/01/1749596.html

【編輯推薦】

  1. 微軟發(fā)布新版Windows 7及.NET 4軟件開發(fā)工具包
  2. 詳解.NET 4.0并行計(jì)算支持歷史
  3. 詳讀.NET 4.0環(huán)境配置
  4. 詳解.NET 4.0中異常處理方面的新特性
  5. 三方面詮釋.NET 4.0的新特性
責(zé)任編輯:彭凡 來源: 博客園
相關(guān)推薦

2010-06-08 08:41:08

.NET 4并行編程

2010-06-04 09:11:10

.NET并行編程

2010-06-09 09:18:34

.NET 4并行編程

2010-06-02 08:53:51

.NET 4并行編程

2010-06-11 09:01:02

.NET 4并行編程

2011-03-24 09:23:43

.NET 4多核并行

2010-06-24 09:12:27

.NET 4并行編程

2015-10-13 09:18:00

.Net編程教程

2024-04-07 09:04:18

Parallel 類編程工具.NET

2024-09-27 19:42:09

工具C#Task?

2024-09-29 16:22:18

多線程TaskC#

2024-06-04 15:56:48

Task?.NET異步編程

2009-07-24 15:41:00

ASP.NET編程入門

2010-04-21 09:23:09

.NET 4

2017-04-25 15:20:11

Python進(jìn)程mpi4py

2011-07-11 09:29:32

PHP面向?qū)ο缶幊?/a>

2024-04-09 08:04:42

C#結(jié)構(gòu)await

2012-04-10 10:04:26

并行編程

2009-02-23 15:20:03

SQL Server數(shù)據(jù)庫ASP.NET

2023-10-30 08:57:19

.Net開發(fā)并行計(jì)算
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)