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

成都創(chuàng)新互聯(lián)公司專注于企業(yè)成都全網(wǎng)營(yíng)銷推廣、網(wǎng)站重做改版、通川網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5場(chǎng)景定制、商城網(wǎng)站建設(shè)、集團(tuán)公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站制作、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為通川等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。
[[11656]]
本篇文章的議題如下:
1.Task基礎(chǔ)介紹
2.Task的創(chuàng)建
3.獲取Task的執(zhí)行結(jié)果
4. 補(bǔ)充細(xì)節(jié)
1.Task基礎(chǔ)介紹
首先我們還是來看看一段簡(jiǎn)單的代碼:
這里展示的只是一段簡(jiǎn)單的代碼,不能顯示出并行編程的特點(diǎn)。但是我們還是從最基本的開始看,慢慢進(jìn)入深一點(diǎn)的話題。
如果你曾經(jīng)用過.NET 中的多線程編程,比較一下,就會(huì)發(fā)現(xiàn):這段代碼雖然在底層還是使用了多線程,但是寫法上卻簡(jiǎn)化了很多,一行代碼就實(shí)現(xiàn)了一個(gè)并行編程。
下面我們就從Task類開始談。
Task類是Task Programming Library(TPL)中最核心的一個(gè)類,下面我將會(huì)像大家展示如何使用一些方法來創(chuàng)建不同類型的Task,
取消Task,等待Task執(zhí)行完成,獲取Task執(zhí)行后的結(jié)果和對(duì)異常進(jìn)行處理。
在開始討論之前,我們首先快速的看看之前的代碼:
這個(gè)命名空間將會(huì)是我們之后在講述并行編程經(jīng)常使用的一個(gè)。這個(gè)空間包含了很多與并行編程有關(guān)的類。
還有一個(gè)要你使用的命名空間是:System.Threading,大家對(duì)這個(gè)應(yīng)該比較熟悉了,之前的多線程編程常常使用到,這個(gè)空間下包含了一些在并行編程中用來協(xié)調(diào)數(shù)據(jù)的一些類。
上面代碼中,最主要的代碼如下:
- Task.Factory.StartNew(() =>
- {
- Console.WriteLine("Hello World");
- });
我們用靜態(tài)方法:Task.Factory.StartNew()來創(chuàng)建了一個(gè)最簡(jiǎn)單的Task--在屏幕上打印一句話。這段代碼確實(shí)簡(jiǎn)單,而且都沒有任何輸入和需要返回的結(jié)果。
下面我們就正式進(jìn)入議題:
2.Task的創(chuàng)建
如果只是創(chuàng)建一個(gè)簡(jiǎn)單的Task,我們只要為該Task提供一個(gè)執(zhí)行體就行了,執(zhí)行體可以是一個(gè)委托delegate或者action。我們之前展示的那段代碼就是采用了lambda表達(dá)式來作為Task的執(zhí)行體。
2.1 創(chuàng)建一個(gè)簡(jiǎn)單的Task
為了執(zhí)行一個(gè)簡(jiǎn)單的Task,一般進(jìn)行以下步驟:
首先,要?jiǎng)?chuàng)建一個(gè)Task類的實(shí)例,
然后,傳入一個(gè)System.Action委托,這個(gè)委托中的方法就是這個(gè)Task運(yùn)行時(shí)你要執(zhí)行的方法,而且這個(gè)委托必須作為Task構(gòu)造函數(shù)的一個(gè)參數(shù)傳入。我們?cè)趥魅胛凶鳛閰?shù)的時(shí)候有多種方式:傳入匿名委托,
Lambda表達(dá)式或者一個(gè)顯示什么方法的委托。
***,調(diào)用Task實(shí)例的Start()方法來運(yùn)行。
當(dāng)這個(gè)Task實(shí)例開始運(yùn)行的時(shí)候,它就被傳給了內(nèi)部的一個(gè)task scheduler,這個(gè)scheduler負(fù)責(zé)把我們創(chuàng)建的task交給底下的線程去執(zhí)行。
下面就看看代碼:
代碼
- using System;
- using System.Threading.Tasks;
- namespace Listing_02
- {
- class Listing_02
- {
- static void Main(string[] args)
- {
- // use an Action delegate and a named method
- Task task1 = new Task(new Action(printMessage));
- // use a anonymous delegate
- Task task2 = new Task(delegate
- {
- printMessage();
- });
- // use a lambda expression and a named method
- Task task3 = new Task(() => printMessage());
- // use a lambda expression and an anonymous method
- Task task4 = new Task(() =>
- {
- printMessage();
- });
- task1.Start();
- task2.Start();
- task3.Start();
- task4.Start();
- // wait for input before exiting
- Console.WriteLine("Main method complete. Press enter to finish.");
- Console.ReadLine();
- }
- static void printMessage()
- {
- Console.WriteLine("Hello World");
- }}}
不知道大家注意到了沒有,上面代碼創(chuàng)建Task的方法和我們之前的***段代碼的創(chuàng)建Task的方法不同。在之前我們采用的是Task.Factory.StartNew()方法來創(chuàng)建的,這個(gè)方法創(chuàng)建Task并且開始運(yùn)行Task,其實(shí)兩端代碼的結(jié)果是一樣的,這里給出一點(diǎn)建議:如果這是想簡(jiǎn)單的創(chuàng)建一個(gè)Task,那么使用Factory.NewStart()來創(chuàng)建,很簡(jiǎn)便,如果像對(duì)所創(chuàng)建的Task附加更多的定制和設(shè)置特定的屬性,那么還是得一步一步的按照我們說的那些步驟來。(詳細(xì)的我們后續(xù)會(huì)介紹的)
2.1 為創(chuàng)建的Task傳入?yún)?shù)
我們之前提過,在創(chuàng)建Task的時(shí)候,我們?cè)跇?gòu)造函數(shù)中傳入了一個(gè)System.Action的委托,如果我們想要把一些參數(shù)傳入到Task中,那么我 們可以傳入System.Action
代碼
- using System;
- using System.Threading.Tasks;
- namespace Listing_04
- {
- class Listing_04
- {
- static void Main(string[] args)
- {
- string[] messages = { "First task", "Second task",
- "Third task", "Fourth task" };
- foreach (string msg in messages)
- {
- Task myTask = new Task(obj => printMessage((string)obj), msg);
- myTask.Start();
- }
- // wait for input before exiting
- Console.WriteLine("Main method complete. Press enter to finish.");
- Console.ReadLine();
- }
- static void printMessage(string message)
- {
- Console.WriteLine("Message: {0}", message);
- }}}
注意:我們?cè)趥魅雲(yún)?shù)后,必須把參數(shù)轉(zhuǎn)換為它們?cè)瓉淼念愋?,然后再去調(diào)用相應(yīng)的方法。例子中,因?yàn)镾ystem.Action對(duì)應(yīng)的方法是printMessage()方法,而這個(gè)方法的要求的參數(shù)類型是string,所以要轉(zhuǎn)換為string。
想向Task傳入?yún)⑺?,只能用System.Action
3.獲取Task的執(zhí)行結(jié)果
如果要獲取Task的結(jié)果,那么在創(chuàng)建Task的時(shí)候,就要采用Task
代碼顯示如下:
代碼
- static void Main(string[] args)
- {
- // create the task
- Task
task1 = new Task (() => - {
- int sum = 0;
- for (int i = 0; i < 100; i++)
- {
- sum += i;
- }
- return sum;
- });
- task1.Start();
- // write out the result
- Console.WriteLine("Result 1: {0}", task1.Result);
- Console.ReadLine();
- }
只有在task執(zhí)行完成之后,才能獲取到Result的值。
下面的代碼展示了如何通過Task.Factory.StartNew
代碼
- static void Main(string[] args)
- {
- // create the task
- Task
task1 = Task.Factory.StartNew (() => - {
- int sum = 0;
- for (int i = 0; i < 100; i++)
- {
- sum += i;
- }
- return sum;
- });
- // write out the result
- Console.WriteLine("Result 1: {0}", task1.Result);
- Console.ReadLine();
- }
4. 補(bǔ)充細(xì)節(jié)
在創(chuàng)建Task的時(shí)候,Task有很多的構(gòu)造函數(shù)的重載,一個(gè)主要的重載就是傳入TaskCreateOptions的枚舉:
TaskCreateOptions.None:用默認(rèn)的方式創(chuàng)建一個(gè)Task
TaskCreateOptions.PreferFairness:請(qǐng)求scheduler盡量公平的執(zhí)行Task(后續(xù)文章會(huì)將是,Task和線程一樣,有優(yōu)先級(jí)的)
TaskCreateOptions.LongRunning:聲明Task將會(huì)長(zhǎng)時(shí)間的運(yùn)行。
TaskCreateOptions.AttachToParent:因?yàn)門ask是可以嵌套的,所以這個(gè)枚舉就是把一個(gè)子task附加到一個(gè)父task中。
***要提到的一點(diǎn)就是,我們可以在Task的執(zhí)行體中用Task.CurrentId來返回Task的唯一表示ID(int)。如果在Task執(zhí)行體外使用這個(gè)屬性就會(huì)得到null。
(熟悉WF的朋友,可以比較Task和WF的一些區(qū)別,因?yàn)槲艺J(rèn)為它們的設(shè)計(jì)思想很相近)
本文標(biāo)題:.NET4并行編程入門之Task基礎(chǔ)
分享鏈接:http://www.dlmjj.cn/article/cdedeij.html


咨詢
建站咨詢
