C# task應(yīng)用實(shí)例詳解
Task的應(yīng)用
Task的MSDN的描述如下:
【Task類的表示單個操作不會返回一個值,通常以異步方式執(zhí)行。
Task對象是一種的中心思想基于任務(wù)的異步模式首次引入.NETFramework 4 中。
因?yàn)橛蓤?zhí)行工作Task對象通常以異步方式執(zhí)行線程池線程上而不是以同步方式在主應(yīng)用程序線程中,可以使用Status屬性,并將IsCanceled, IsCompleted,和IsFaulted屬性,以確定任務(wù)的狀態(tài)。
大多數(shù)情況下,lambda 表達(dá)式用于指定該任務(wù)所執(zhí)行的工作量。
對于返回值的操作,您使用Task類?!?/p>
我對于Task的理解是這樣的,Task是FrameWork4引進(jìn)的新功能,他和ConCurrent命名空間一起被引進(jìn),用來替代Thread的使用。
根據(jù)我的使用,個人覺得,他確實(shí)比Thead的功能要豐富一些。
下面我們一起看一個最簡單的例子:
using System; using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;namespace TaskConsole { class Program { static void Main(string[] args) { //當(dāng)前線程標(biāo)識 Console.WriteLine(Thread.CurrentThread.GetHashCode()); Task task = new Task(run); Console.WriteLine("任務(wù)標(biāo)識:" + task.GetHashCode() + ",狀態(tài):" + task.Status);//狀態(tài) task.Start(); Console.WriteLine("任務(wù)標(biāo)識:" + task.GetHashCode() + ",狀態(tài):" + task.Status);//狀態(tài) //任務(wù)完成后執(zhí)行新任務(wù) Action ation = new Action(taskStart); task.ContinueWith(ation); Console.Read(); } public static void taskStart(Task task) { task = new Task(run); task.Start(); //如果注釋上面兩句話,則任務(wù)標(biāo)識為 task.ContinueWith(ation)中task的任務(wù) Console.WriteLine("任務(wù)標(biāo)識:" + task.GetHashCode() + ",狀態(tài):" + task.Status + ",當(dāng)前線程:" + Thread.CurrentThread.GetHashCode());//狀態(tài) } public static void run() { Console.WriteLine("this is run"); } } }
一,task.GetHashCode(),是獲取Task實(shí)例的唯一標(biāo)識,每個Task都不一樣。
測試發(fā)現(xiàn),Task.GetHashCode()并不等于Thread.CurrentThread.GetHashCode()。
二,task.ContinueWith(),是任務(wù)結(jié)束后繼續(xù)執(zhí)行任務(wù)的方法,傳一個Action,當(dāng)任務(wù)結(jié)束后,觸發(fā)該Action。
任務(wù)剛new出來的時候,task就又狀態(tài)了,是Created,一但運(yùn)行了,狀態(tài)就是WaitingToRun。
運(yùn)行結(jié)果如下:
根據(jù)MSDN的說明,Task.State是獲取TaskState的枚舉值,其枚舉值代表的意義如下
|Canceled |該任務(wù)已通過對其自身的 CancellationToken 引發(fā) OperationCanceledException 對取消進(jìn)行了確認(rèn),此時該標(biāo)記處于已發(fā)送信號狀態(tài);或者在該任務(wù)開始執(zhí)行之前,已向該任務(wù)的 CancellationToken 發(fā)出了信號。 有關(guān)更多信息,請參見任務(wù)取消。
| Created |該任務(wù)已初始化,但尚未被計劃。
| Faulted |由于未處理異常的原因而完成的任務(wù)。
| RanToCompletion |已成功完成執(zhí)行的任務(wù)。
| Running |該任務(wù)正在運(yùn)行,但尚未完成。
| WaitingForActivation |該任務(wù)正在等待 .NET Framework 基礎(chǔ)結(jié)構(gòu)在內(nèi)部將其激活并進(jìn)行計劃。
| WaitingForChildrenToComplete |該任務(wù)已完成執(zhí)行,正在隱式等待附加的子任務(wù)完成。
| WaitingToRun |該任務(wù)已被計劃執(zhí)行,但尚未開始執(zhí)行。
任務(wù)嵌套
任務(wù)嵌套就是指在一個任務(wù)中又創(chuàng)建了一個任務(wù)。
而新建的任務(wù)就是子任務(wù)。在沒有特殊聲明的情況下,父子任務(wù)是一起運(yùn)行的。
如SimpleNestedTask方法。
父子任務(wù)關(guān)聯(lián)需要在創(chuàng)建子任務(wù)的時候,增加參數(shù)TaskCreationOptions.AttachedToParent。
將父子任務(wù)關(guān)聯(lián)起來,此時父任務(wù)將等待子任務(wù)結(jié)束,才會完成。
如果使用Task創(chuàng)建任務(wù),不需要使用TaskCreationOptions.AttachedToParent參數(shù),因?yàn)橹灰溉蝿?wù)使用了子任務(wù)的返回結(jié)果,父任務(wù)自然就會等待子任務(wù)完成。
public class Program { static void Main(string[] args) { WaitForSimpleNestedTask(); Console.WriteLine("====================================================="); SimpleNestedTask(); Thread.SpinWait(600000);//等待SimpleNestedTask結(jié)束 再運(yùn)行 Console.WriteLine("====================================================="); //SimpleNestedTaskAttachedToParent(); Console.Read(); } static void WaitForSimpleNestedTask() { var outer = Task.Factory.StartNew(() => { Console.WriteLine("Outer1 task executing."); var nested = Task.Factory.StartNew(() => { Console.WriteLine("Nested1 task starting."); Thread.SpinWait(5000000); Console.WriteLine("Nested1 task completing."); return 42; }); return nested.Result; return 1; }); Console.WriteLine("Outer1 has returned {0}.", outer.Result); } static void SimpleNestedTask() { var parent = Task.Factory.StartNew(() => { Console.WriteLine("Outer2 task executing."); var child = Task.Factory.StartNew(() => { Console.WriteLine("Nested2 task starting."); Thread.SpinWait(500000); Console.WriteLine("Nested2 task completing."); }); }); parent.Wait(); Console.WriteLine("Outer2 has completed."); } static void SimpleNestedTaskAttachedToParent() { var parent = Task.Factory.StartNew(() => { Console.WriteLine("Outer3 task executing."); var child = Task.Factory.StartNew(() => { Console.WriteLine("Nested3 task starting."); Thread.SpinWait(500000); Console.WriteLine("Nested3 task completing."); }, TaskCreationOptions.AttachedToParent); }); parent.Wait(); Console.WriteLine("Outer has completed."); }
ConCurrent的線程安全的
因?yàn)椋琈SDN將在System.Collections.Concurrent命名空間下的集合,都稱為線程安全的集合。
線程安全可以理解為可以被多個線程同時使用的集合,而且同時使用的時候是該集合的值是準(zhǔn)確的。
下面舉一個使用線程安全集合的例子,使用的是BlockingCollection。
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ParallelConsole { class Program { //定義集合大小為51個,也可以不定義大小 static BlockingCollection blocking = new BlockingCollection(51); static void Main(string[] args) { blocking = new BlockingCollection(); Console.WriteLine("當(dāng)前blocking為:" + blocking.IsCompleted + "設(shè)置了集合大小count一樣是0,blocking.Count:" + blocking.Count()); //當(dāng)前線程標(biāo)識 Console.WriteLine(Thread.CurrentThread.GetHashCode()); for (int i = 0; i < 3; i++) { ////如果添加到第3個,就設(shè)置添加完成,這時在添加就會拋異常 //if (i == 3) //{ // blocking.CompleteAdding(); //} Action action = new Action(run); Task task = new Task(action,i); task.RunSynchronously(); } Console.WriteLine("設(shè)置添加完成前:" + blocking.IsAddingCompleted); //設(shè)置添加完成后 blocking.CompleteAdding(); Console.WriteLine("設(shè)置添加完成后:" + blocking.IsAddingCompleted); #region 同步取 取3個 //for (int i = 0; i < 3; i++) //{ // Action actionTake = new Action(take); // actionTake(); //} #endregion //并發(fā)讀取 #region 并發(fā)步取 取3個 //blocking.IsCompleted 只有當(dāng)集合被添加進(jìn)內(nèi)容,然后又都被取光了以后,他才會等于ture,否則都是false //當(dāng)IsCompleted為ture時,就不能再取了否則會拋異常 //同時取,結(jié)果是 //blocking:0 //blocking:2 //blocking:1 if (!blocking.IsCompleted)//如果集合沒取光 { Action actionTake2 = new Action(take); Parallel.Invoke(actionTake2, actionTake2, actionTake2); } #endregion Console.WriteLine("當(dāng)前blocking為:" + blocking.IsCompleted + ",blocking數(shù)量為:" + blocking.Count()); //數(shù)據(jù)被取光了以后, blocking.Count()為0 Console.Read(); } public static void take() { //同步取,blocking.Count()會真實(shí)的表現(xiàn),而異步取,Count是不準(zhǔn)確的,因?yàn)槲胰ount的時候,可能集合已經(jīng)又被取出數(shù)據(jù)了,測試10次肯定會出現(xiàn)不真實(shí)的情況 Console.WriteLine("blocking:" + blocking.Take() + ",blocking數(shù)量為:" + blocking.Count()); } public static void run(object i) { int currentI = int.Parse(i.ToString()); blocking.TryAdd(currentI); } } }
Parallel
Parallel.Invoke(),并發(fā)調(diào)用Action,可以傳多個Action,也可以傳一個Action數(shù)據(jù)組。
Task
Task(Action,object),這是Task的構(gòu)造方法,接收Action,object是Action的參數(shù),。
task.RunSynchronously(),他是同步運(yùn)行任務(wù)計劃用的,同時他和task.Start()一樣,也可以啟動線程。
BlockingCollection集合
屬性一:IsCompleted,他是表示集合是否有數(shù)據(jù),只有當(dāng)集合被添加進(jìn)內(nèi)容,然后又都被取光了以后,他才會等于ture,否則都是false。
屬性一:BlockingCollection.IsAddingCompleted,表示是否添加完成。針對blocking.CompleteAdding()的使用,當(dāng)調(diào)用了該方法IsAddingCompleted就為true。
方法一:BlockingCollection.blocking.CompleteAdding(),設(shè)置IsAddingCompleted用的。
方法二:BlockingCollection.Add,添加一個實(shí)體
方法三:BlockingCollection.TryAdd,添加一個實(shí)體,我這里用的是這個方法,區(qū)別是,如果添加重復(fù)項(xiàng),他會引發(fā)InvalidOperationException這個異常。
方法四:BlockingCollection.Take,從集合中取一個值,注意,是真的取出來,取出來后,BlockingCollection.cout會減一。
運(yùn)行結(jié)果如下:
到此這篇關(guān)于C# task應(yīng)用實(shí)例的文章就介紹到這了,更多相關(guān)c#task應(yīng)用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#實(shí)現(xiàn)給函數(shù)添加注釋的小技巧分享
這篇文章主要介紹了C#實(shí)現(xiàn)給函數(shù)添加注釋的小技巧,文中通過代碼示例給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-04-04Stream.Write 與 StreamWriter.Write 的不同
Stream.Write 與 StreamWriter.Write 是我們在向流中寫數(shù)據(jù)時,最常用的方法。下面就詳細(xì)講解這兩個方法。2013-04-04Chrome Visual Studio 2005下的編譯過程
研究Chrome ,首先得把它編譯出來,這對于后續(xù)的代碼分析和閱讀有很大的幫助,想想自己編譯出一個 Chrome 瀏覽器來使用,那是一件很炫的事情。2009-07-07C#中Dictionary<TKey,TValue>排序方式的實(shí)現(xiàn)
這篇文章主要介紹了C#中Dictionary<TKey,TValue>排序方式的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02ADO.NET實(shí)體數(shù)據(jù)模型詳細(xì)介紹
本文將詳細(xì)介紹ADO.NET實(shí)體數(shù)據(jù)模型,下面先看看簡單的單表的增刪改查操作,然后再看多表的關(guān)聯(lián)查詢,帶參數(shù)查詢等2012-11-11.Net(c#)漢字和Unicode編碼互相轉(zhuǎn)換實(shí)例
下面小編就為大家?guī)硪黄?Net(c#)漢字和Unicode編碼互相轉(zhuǎn)換實(shí)例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02C#中FormClosing與FormClosed的區(qū)別詳細(xì)解析
本文是對C#中FormClosing與FormClosed的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下,希望對大家有所幫助2013-10-10