.Net中Task Parallel Library的基本用法
我們知道,每個(gè)應(yīng)用程序就是一個(gè)進(jìn)程,一個(gè)進(jìn)程有多個(gè)線程。Task Parallel Library為我們的異步編程、多線程編程提供了強(qiáng)有力的支持,它允許一個(gè)主線程運(yùn)行的同時(shí),另外的一些線程或Task也同時(shí)運(yùn)行。本篇體驗(yàn)基本用法。
基本用法
Taks的構(gòu)造函數(shù)接收的類(lèi)型是Action,也就是一個(gè)委托。
static void Main(string[] args){ var t1 = new Task(() => {Console.WriteLine("任務(wù)1開(kāi)始");Thread.Sleep(1000);Console.WriteLine("任務(wù)1結(jié)束"); }); t1.Start(); Console.ReadKey();}
如果把方法放到外面。
static void Main(string[] args){ var t1 = new Task(() => DoSth(1,2000)); t1.Start(); Console.ReadKey();}static void DoSth(int id, int sleepTime){ Console.WriteLine("任務(wù){(diào)0}開(kāi)始",id); Thread.Sleep(sleepTime); Console.WriteLine("任務(wù){(diào)0}結(jié)束",id);}
如果有多個(gè)Task同時(shí)執(zhí)行。
static void Main(string[] args){ var t1 = new Task(() => DoSth(1,2000)); t1.Start(); var t2 = new Task(() => DoSth(2, 1500)); t2.Start(); var t3 = new Task(() => DoSth(3, 3000)); t3.Start(); Console.ReadKey();}
如果有很多Task,每個(gè)Task手動(dòng)啟動(dòng)的話很費(fèi)事,Task Parallel Library為我們準(zhǔn)備了Task工廠。
static void Main(string[] args){ var t1 = Task.Factory.StartNew(() => DoSth(1, 2000)); var t2 = Task.Factory.StartNew(() => DoSth(2, 1500)); var t3 = Task.Factory.StartNew(() => DoSth(3, 3000)); Console.ReadKey();}
如果我們想在一個(gè)任務(wù)結(jié)束之后立即執(zhí)行某個(gè)任務(wù),可以使用ContinueWith方法。
static void Main(string[] args){ var t1 = Task.Factory.StartNew(() => DoSth(1, 2000)).ContinueWith((pre)=> DoOtherThing(4,2000)); var t2 = Task.Factory.StartNew(() => DoSth(2, 1500)); var t3 = Task.Factory.StartNew(() => DoSth(3, 3000)); Console.ReadKey();}static void DoSth(int id, int sleepTime){ Console.WriteLine("任務(wù){(diào)0}開(kāi)始",id); Thread.Sleep(sleepTime); Console.WriteLine("任務(wù){(diào)0}結(jié)束",id);}static void DoOtherThing(int id, int sleepTime){ Console.WriteLine("其他任務(wù){(diào)0}開(kāi)始", id); Thread.Sleep(sleepTime); Console.WriteLine("其他任務(wù){(diào)0}結(jié)束", id);}
如果希望等待所有的Task執(zhí)行完畢,使用WaitAll方法。
static void Main(string[] args){ var t1 = Task.Factory.StartNew(() => DoSth(1, 2000)); var t2 = Task.Factory.StartNew(() => DoSth(2, 1500)); var t3 = Task.Factory.StartNew(() => DoSth(3, 3000)); var taskList = new List<Task> {t1, t2, t3}; Task.WaitAll(taskList.ToArray()); Console.WriteLine("我是在所有Task執(zhí)行完畢后才執(zhí)行的"); Console.ReadKey();}
如果想手動(dòng)取消結(jié)束某個(gè)Task,需要為方法帶上CancellationToken類(lèi)型參數(shù)。
static void Main(string[] args){ var source = new CancellationTokenSource(); try {var t1 = Task.Factory.StartNew(() => DoSth(1, 1000, source.Token)).ContinueWith((pre) => DoOtherThing(2, 2000));source.Cancel(); } catch (Exception ex) {Console.WriteLine(ex.GetType()); } Console.WriteLine("haha"); Console.ReadKey();}static void DoSth(int id, int sleepTime, CancellationToken token){ if (token.IsCancellationRequested) {Console.WriteLine("任務(wù)被取消");token.ThrowIfCancellationRequested(); } Console.WriteLine("任務(wù){(diào)0}開(kāi)始",id); Thread.Sleep(sleepTime); Console.WriteLine("任務(wù){(diào)0}結(jié)束",id);}static void DoOtherThing(int id, int sleepTime){ Console.WriteLine("其他任務(wù){(diào)0}開(kāi)始", id); Thread.Sleep(sleepTime); Console.WriteLine("其他任務(wù){(diào)0}結(jié)束", id);}
如何從Task從獲取方法的返回結(jié)果呢?
static void Main(string[] args){ Console.WriteLine("開(kāi)始計(jì)算"); Task<int> t = Task.Factory.StartNew(() => Sum(1, 2)); Console.WriteLine("等待結(jié)果"); Console.WriteLine(t.Result); Console.ReadKey();}static int Sum(int a, int b){ return a + b;}
后面一個(gè)Task獲取前面一個(gè)Task的返回值。
static void Main(string[] args){ Task<string> firstTask = Task.Factory.StartNew<string>(() => {Console.WriteLine("第一個(gè)任務(wù)開(kāi)始");return "hi from the one"; }); Task secondTask = firstTask.ContinueWith((prevoursTask) => {Console.WriteLine("這里是第二個(gè)任務(wù),獲取到第一個(gè)任務(wù)的返回值是{0}",prevoursTask.Result,TaskContinuationOptions.OnlyOnRanToCompletion); }); secondTask.Wait(); Console.ReadKey();}
等待所有Task完成。
static void Main(string[] args){ var t1 = Task.Factory.StartNew(() => {Console.WriteLine("第一個(gè)任務(wù)");Thread.Sleep(1000); }); var t2 = Task.Factory.StartNew(() => {Console.WriteLine("第二個(gè)任務(wù)");Thread.Sleep(1000); }); var taskList = new List<Task> {t1, t2}; Task.Factory.ContinueWhenAll(taskList.ToArray(), (t) => { Console.WriteLine("所有任務(wù)完成我就出來(lái)"); }); Console.ReadKey();}
如果是嵌套Task。
static void Main(string[] args){ Task.Factory.StartNew(() => {Task child = Task.Factory.StartNew(() =>{ Console.WriteLine("我是子任務(wù)");}, TaskCreationOptions.AttachedToParent); }).Wait(); Console.ReadKey();}
啟動(dòng)Task的幾種方式
1、通過(guò)Task.Factory.StartNew方法。
static void Main(string[] args){ Task.Factory.StartNew(() => SaySth("hello")); Console.ReadKey();}static void SaySth(string msg){ Console.WriteLine(msg);}
2、通過(guò)Task的Start實(shí)例方法
static void Main(string[] args){ var t = new Task(() => SaySth("hello")); t.Start(); Console.ReadKey();}
或者干脆用委托。
static void Main(string[] args){ Task t = new Task(delegate {SaySth("hello");}); t.Start(); Console.ReadKey();}
3、Task的靜態(tài)方法Run
static void Main(string[] args){ Task t = Task.Run(() => SaySth("hello")); Console.ReadKey();}static void SaySth(string msg){ Console.WriteLine(msg);}
一個(gè)例子
比如說(shuō)要下載某個(gè)頁(yè)面,在保持當(dāng)前UI界面無(wú)影響的情況下,使用Task在后臺(tái)啟動(dòng)任務(wù)下載某個(gè)頁(yè)面。
static void Main(string[] args){ Console.WriteLine("界面內(nèi)容"); Task<string> r = DownloadAsync("http://www.baidu.com"); while (!r.IsCompleted) {Console.Write(".");Thread.Sleep(250); } Console.WriteLine(r.Result); Console.ReadKey();}private static string DownloadWebPage(string url){ WebRequest request = WebRequest.Create(url); WebResponse response = request.GetResponse(); var reader = new StreamReader(response.GetResponseStream()); return reader.ReadToEnd();}private static Task<string> DownloadAsync(string url){ return Task.Factory.StartNew(() => DownloadWebPage(url));}
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
相關(guān)文章:
1. .NET6使用ImageSharp實(shí)現(xiàn)給圖片添加水印2. asp.net core應(yīng)用docke部署到centos7的全過(guò)程3. .NET Core Web APi類(lèi)庫(kù)內(nèi)嵌運(yùn)行的方法4. ASP.Net Core對(duì)USB攝像頭進(jìn)行截圖5. ASP.NET MVC實(shí)現(xiàn)橫向展示購(gòu)物車(chē)6. 一文透徹詳解.NET框架類(lèi)型系統(tǒng)設(shè)計(jì)要點(diǎn)7. .net如何優(yōu)雅的使用EFCore實(shí)例詳解8. ASP.NET MVC使用Boostrap實(shí)現(xiàn)產(chǎn)品展示、查詢(xún)、排序、分頁(yè)9. ASP.Net Core(C#)創(chuàng)建Web站點(diǎn)的實(shí)現(xiàn)10. .NET使用Moq進(jìn)行單元測(cè)試
