.Net中Task Parallel Library的進(jìn)階用法
在前一篇中,了解了Task的基本用法
如果一個(gè)方法返回Task,Task<T>,如何獲取Task的返回值,獲取值的過程會(huì)阻塞線程嗎?
static void Main(string[] args) { var result = DoWorkAsync().Result; Console.WriteLine(result); Console.WriteLine("我會(huì)什么時(shí)候顯示"); Console.ReadKey(); } static Task<string> DoWorkAsync() { return Task<string>.Factory.StartNew(() => { Thread.Sleep(3000); return "hello"; }); }
可見,Task的Result屬性可以獲取返回值,而且,獲取返回值的過程線程是被阻塞的。
是否可以不阻塞線程,又能拿到某個(gè)線程的返回值呢?ContinueWith方法在某個(gè)線程結(jié)束之后進(jìn)行,但同時(shí)不會(huì)阻塞線程。
static void Main(string[] args) { DoWorkAsync().ContinueWith((pre) => { Console.WriteLine(pre.Result); }); Console.WriteLine("我會(huì)什么時(shí)候顯示"); Console.ReadKey(); }
但ContinueWith總會(huì)在某個(gè)線程結(jié)束之后進(jìn)行,是否可以對ContinueWith的過程控制一下呢?
static void Main(string[] args) { DoWorkAsync().ContinueWith((pre) => { Console.WriteLine(pre.Result); }, TaskContinuationOptions.NotOnFaulted); DoWorkAsync().ContinueWith((pre) => { Console.WriteLine(pre.Exception); },TaskContinuationOptions.OnlyOnFaulted); Console.WriteLine("我會(huì)什么時(shí)候顯示"); Console.ReadKey(); }
以上,當(dāng)沒有錯(cuò)誤的時(shí)候就把返回值顯示出來,有錯(cuò)誤就把錯(cuò)誤信息顯示出來。
還可以通過Task的實(shí)例方法IsCompleted來判斷一個(gè)線程是否完成。
static void Main(string[] args) { var doWorkTask = DoWorkAsync(); if (doWorkTask.IsCompleted) { Console.WriteLine(doWorkTask.Result); } else { doWorkTask.ContinueWith((pre) => { Console.WriteLine(pre.Result); }, TaskContinuationOptions.NotOnFaulted); doWorkTask.ContinueWith((pre) => { Console.WriteLine(pre.Exception); }, TaskContinuationOptions.OnlyOnFaulted); } Console.WriteLine("我會(huì)什么時(shí)候顯示"); Console.ReadKey(); }
Task的Status屬性,以及結(jié)合TaskStatus枚舉,可以判斷Task的狀態(tài)。
static void Main(string[] args) { var httpClient = new HttpClient(); Task<string> baiduTask = httpClient.GetStringAsync("http://www.baidu.com"); var httpClient2 = new HttpClient(); Task<string> sinaTask = httpClient2.GetStringAsync("http://www.sina.com.cn"); //等上面2個(gè)任務(wù)完成時(shí)這里再開始 Task<string[]> task = Task.WhenAll(baiduTask, sinaTask); task.ContinueWith(stringArray => { //如果任務(wù)完成 if (task.Status == TaskStatus.RanToCompletion) { for (int i = 0; i < stringArray.Result.Length;i++) { Console.WriteLine(stringArray.Result[i].Substring(0,100)); } } else if (task.Status == TaskStatus.Canceled) //如果被取消 { Console.WriteLine("{0}這個(gè)任務(wù)被取消了",task.Id); } else //發(fā)生錯(cuò)誤 { Console.WriteLine("發(fā)生錯(cuò)誤了~~"); foreach (var item in task.Exception.InnerExceptions) { Console.WriteLine(item.Message); } } }); Console.ReadKey(); }
如果要控制Task的生命周期,可以考慮使用TaskCompletionSource<T>。
static void Main(string[] args) { AsyncFactory.GetIntAsync().ContinueWith((prev) => { if (prev.Status == TaskStatus.RanToCompletion) { Console.WriteLine(prev.Result); } else if (prev.Status == TaskStatus.Canceled) { Console.WriteLine("任務(wù)被取消"); } else { Console.WriteLine("發(fā)生錯(cuò)誤哦"); Console.WriteLine(prev.Exception); } }); Console.ReadKey(); } } public static class AsyncFactory { public static Task<int> GetIntAsync() { var tsc = new TaskCompletionSource<int>(); var timer = new System.Timers.Timer(2000); timer.AutoReset = false; timer.Elapsed += (s, e) => { tsc.SetResult(10); timer.Dispose(); }; timer.Start(); return tsc.Task; } }
以上,通過TaskCompletionSource<T>的SetResult給線程設(shè)置返回值,通過TaskCompletionSource<T>的.Task有獲取了線程。
另外,從.NET 4.5開始,Task的靜態(tài)方法FromResult,接收T類型,返回Task<T>。
static void Main(string[] args) { var intTask = GetIntAsync(); if (intTask.Status == TaskStatus.RanToCompletion) { Console.WriteLine(intTask.Result); } else if (intTask.Status == TaskStatus.Canceled) { Console.WriteLine("任務(wù)被取消"); } else { Console.WriteLine("發(fā)生錯(cuò)誤哦"); Console.WriteLine(intTask.Exception); } Console.ReadKey(); } static Task<int> GetIntAsync() { return Task.FromResult(10); }
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接
相關(guān)文章
詳解.NET中string與StringBuilder在字符串拼接功能上的比較
string與StringBuilder的在字符串拼接時(shí)執(zhí)行效率上有差異,這篇文章主要介紹了詳解.NET中string與StringBuilder在字符串拼接功能上的比較,感興趣的小伙伴們可以參考一下2018-11-11.NET中讀取Excel文件的數(shù)據(jù)及excelReader應(yīng)用
輕量,快速的C#編寫的庫讀取Microsoft Excel文件,這對讀取大量excel文件的朋友們很有幫助而且可以學(xué)習(xí)下ExcelDataReader的應(yīng)用,感興趣的朋友可以了解下,或許對你有所幫助2013-02-02VB.NET設(shè)置屏幕分辨率、顏色位數(shù)、刷新率 實(shí)例代碼
這篇文章介紹了VB.NET設(shè)置屏幕分辨率、顏色位數(shù)、刷新率 實(shí)例代碼,有需要的朋友可以參考一下2013-07-07VB.NET驗(yàn)證郵件地址的合法性實(shí)現(xiàn)代碼
現(xiàn)在,對于用戶在Web頁面上或電話中給出的Email地址,我們越來越不敢肯定它是否真的有效。在今天這個(gè)垃圾郵件泛濫成災(zāi)的年代,人們完全有理由舍不得輕易透露Email地址。2011-04-04ASP.NET實(shí)現(xiàn)數(shù)據(jù)的添加(第10節(jié))
這篇文章主要介紹了ASP.NET如何實(shí)現(xiàn)數(shù)據(jù)的添加,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2015-08-08基于.net standard 的動(dòng)態(tài)編譯實(shí)現(xiàn)代碼
這篇文章主要介紹了基于.net standard 的動(dòng)態(tài)編譯實(shí)現(xiàn)代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-07-07