網(wǎng)站首頁 編程語言 正文
一、基本概念
Task優(yōu)勢
ThreadPool相比Thread來說具備了很多優(yōu)勢,但是ThreadPool卻又存在一些使用上的不方便,例如:
- ThreadPool不支持線程的取消、完成、失敗通知等交互性操作;
- ThreadPool不支持線程執(zhí)行的先后次序;
.NET Framework 在4.0的時(shí)候提供了一個(gè)功能更強(qiáng)大的概念:Task。Task在ThreadPool的基礎(chǔ)上進(jìn)行了優(yōu)化,并提供了更多的API。看下面一個(gè)簡單的示例:
using System; using System.Threading; using System.Threading.Tasks; namespace TaskDemo { class Program { static void Main(string[] args) { // 創(chuàng)建Task Task t = new Task(() => { Console.WriteLine("任務(wù)開始工作....."); Thread.Sleep(5000); }); // 啟動(dòng) t.Start(); t.ContinueWith((task) => { Console.WriteLine("任務(wù)完成,完成時(shí)候的狀態(tài)為:"); Console.WriteLine("IsCanceled={0}\tIsCompleted={1}\tIsFaulted={2}", task.IsCanceled, task.IsCompleted, task.IsFaulted); }); Console.WriteLine("啟動(dòng)"); Console.ReadKey(); } } }
二、Task用法
創(chuàng)建任務(wù)
Task創(chuàng)建的任務(wù)可以分為有返回值和無返回值兩種。
1、使用Task創(chuàng)建無返回值
先看一下Task的定義:
可以看到Task構(gòu)造函數(shù)的參數(shù)是Action委托。所以使用Task創(chuàng)建任務(wù)的代碼如下:
using System; using System.Threading; using System.Threading.Tasks; namespace TaskDemo { class Program { static void Main(string[] args) { #region 1、使用Task創(chuàng)建任務(wù) Task task = new Task(() => TaskMethod("Task 1")); Console.WriteLine("before start status:"+task.Status); // Task創(chuàng)建的任務(wù)必須調(diào)用start方法才能啟動(dòng) task.Start(); Console.WriteLine("after start status:" + task.Status); #endregion Console.ReadKey(); } static void TaskMethod(string name) { Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}", name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); } } }
程序運(yùn)行結(jié)果:
注:任務(wù)的狀態(tài),Start之前為Created,Start之后為WaitingToRun。
2、使用Task.Run方法創(chuàng)建任務(wù)
Task.Run創(chuàng)建的任務(wù)可以執(zhí)行啟動(dòng):
using System; using System.Threading; using System.Threading.Tasks; namespace TaskDemo { class Program { static void Main(string[] args) { #region 1、使用Task創(chuàng)建任務(wù) //Task task = new Task(() => TaskMethod("Task 1")); //Console.WriteLine("before start status:"+task.Status); //// Task創(chuàng)建的任務(wù)必須調(diào)用start方法才能啟動(dòng) //task.Start(); //Console.WriteLine("after start status:" + task.Status); #endregion #region 2、使用Task.Run創(chuàng)建任務(wù) Task.Run(() => TaskMethod("Task Run")); #endregion Console.ReadKey(); } static void TaskMethod(string name) { Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}", name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); } } }
程序運(yùn)行結(jié)果:
3、使用Factory方式創(chuàng)建任務(wù)
using System; using System.Threading; using System.Threading.Tasks; namespace TaskDemo { class Program { static void Main(string[] args) { #region 1、使用Task創(chuàng)建任務(wù) //Task task = new Task(() => TaskMethod("Task 1")); //Console.WriteLine("before start status:"+task.Status); //// Task創(chuàng)建的任務(wù)必須調(diào)用start方法才能啟動(dòng) //task.Start(); //Console.WriteLine("after start status:" + task.Status); #endregion #region 2、使用Task.Run創(chuàng)建任務(wù) // Task.Run(() => TaskMethod("Task Run")); #endregion #region 3、使用Factory創(chuàng)建任務(wù) // 使用Task.Factory創(chuàng)建 Task.Factory.StartNew(() => TaskMethod("Task 4")); //標(biāo)記為長時(shí)間運(yùn)行任務(wù),則任務(wù)不會(huì)使用線程池,而在單獨(dú)的線程中運(yùn)行。 Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning); // 實(shí)例化TaskFactory對象,然后創(chuàng)建 TaskFactory factory = new TaskFactory(); factory.StartNew(() => TaskMethod("Task 6")); #endregion Console.ReadKey(); } static void TaskMethod(string name) { Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}", name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); } } }
程序運(yùn)行結(jié)果:
4、創(chuàng)建帶返回值的Task
代碼如下:
using System; using System.Threading; using System.Threading.Tasks; namespace TaskDemo { class Program { static void Main(string[] args) { #region 1、使用Task創(chuàng)建任務(wù) //Task task = new Task(() => TaskMethod("Task 1")); //Console.WriteLine("before start status:"+task.Status); //// Task創(chuàng)建的任務(wù)必須調(diào)用start方法才能啟動(dòng) //task.Start(); //Console.WriteLine("after start status:" + task.Status); #endregion #region 2、使用Task.Run創(chuàng)建任務(wù) // Task.Run(() => TaskMethod("Task Run")); #endregion #region 3、使用Task.Factory創(chuàng)建任務(wù) //Task.Factory.StartNew(() => TaskMethod("Task 4")); ////標(biāo)記為長時(shí)間運(yùn)行任務(wù),則任務(wù)不會(huì)使用線程池,而在單獨(dú)的線程中運(yùn)行。 //Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning); #endregion #region 4、創(chuàng)建帶返回值的任務(wù) TaskMethodReturn("Main Thread Task"); // 創(chuàng)建帶返回值的Task Tasktask = CreateTask("Task 1"); // 啟動(dòng) task.Start(); // 獲取返回值 int result1 = task.Result; Console.WriteLine($"Task 1 Result is:{result1}"); Task task2 = new Task (() => TaskMethodReturn("Task 2")); task2.Start(); int result2 = task2.Result; Console.WriteLine($"Task 2 Result is:{result2}"); int result3= Task.Run (() => TaskMethodReturn("Task 3")).Result; Console.WriteLine($"Task 3 Result is:{result3}"); int result4 = Task.Factory.StartNew (() => TaskMethodReturn("Task 4")).Result; Console.WriteLine($"Task 4 Result is:{result4}"); #endregion Console.ReadKey(); } /// /// 返回一個(gè)Task /// ////// static Task CreateTask(string name) { // 參數(shù)是Func return new Task (() => TaskMethodReturn(name)); } static void TaskMethod(string name) { Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}", name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); } static int TaskMethodReturn(string name) { Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}", name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); Thread.Sleep(TimeSpan.FromSeconds(2)); return 42; } } }
程序運(yùn)行結(jié)果:
我們在文章開始的時(shí)候說過,Task是基于ThreadPool的,那么怎么證明呢?看下面的代碼:
////// 測試Task的線程來自于ThreadPool /// static void Test() { // 設(shè)置線程池中最大的線程數(shù) ThreadPool.SetMaxThreads(6, 6); // 創(chuàng)建Task的集合 ListtaskList = new List (); // 創(chuàng)建int類型的集合,用于存放線程ID List threadIdList = new List (); // 使用Task循環(huán)創(chuàng)建50個(gè)線程 for (int i = 0; i < 30; i++) { int k = i; Task task = Task.Run(() => { // 當(dāng)前線程ID加入到集合中 threadIdList.Add(Thread.CurrentThread.ManagedThreadId); Console.WriteLine($"this is {k} 循環(huán) ThreadID:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"); // 休眠 Thread.Sleep(200); }); // 把task加入到集合中 taskList.Add(task); } // 等待所有的線程執(zhí)行完 Task.WaitAll(taskList.ToArray()); // 輸出總數(shù)量 Console.WriteLine($"線程總數(shù):{threadIdList.Distinct().Count()}"); }
程序運(yùn)行結(jié)果:
從結(jié)果中可以看出,Task中的線程確實(shí)是來自于ThreadPool。
三、常見方法
我們以下面的一個(gè)例子來講解Task中比較常見的幾個(gè)方法。多名開發(fā)者合作開發(fā)一個(gè)項(xiàng)目,每個(gè)人負(fù)責(zé)一個(gè)模塊的開發(fā),我們可以把這個(gè)過程認(rèn)為是多線程,代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace TaskDemo { class Program { static void Main(string[] args) { #region 1、使用Task創(chuàng)建任務(wù) //Task task = new Task(() => TaskMethod("Task 1")); //Console.WriteLine("before start status:"+task.Status); //// Task創(chuàng)建的任務(wù)必須調(diào)用start方法才能啟動(dòng) //task.Start(); //Console.WriteLine("after start status:" + task.Status); #endregion #region 2、使用Task.Run創(chuàng)建任務(wù) // Task.Run(() => TaskMethod("Task Run")); #endregion #region 3、使用Factory創(chuàng)建任務(wù) // 使用Task.Factory創(chuàng)建 //Task.Factory.StartNew(() => TaskMethod("Task 4")); ////標(biāo)記為長時(shí)間運(yùn)行任務(wù),則任務(wù)不會(huì)使用線程池,而在單獨(dú)的線程中運(yùn)行。 //Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning); // 實(shí)例化TaskFactory對象,然后創(chuàng)建 //TaskFactory factory = new TaskFactory(); //factory.StartNew(() => TaskMethod("Task 6")); #endregion #region 4、創(chuàng)建帶返回值的任務(wù) //TaskMethodReturn("Main Thread Task"); //// 創(chuàng)建帶返回值的Task //Tasktask = CreateTask("Task 1"); //// 啟動(dòng) //task.Start(); //// 獲取返回值 //int result1 = task.Result; //Console.WriteLine($"Task 1 Result is:{result1}"); //Task task2 = new Task (() => TaskMethodReturn("Task 2")); //task2.Start(); //int result2 = task2.Result; //Console.WriteLine($"Task 2 Result is:{result2}"); //int result3= Task.Run (() => TaskMethodReturn("Task 3")).Result; //Console.WriteLine($"Task 3 Result is:{result3}"); //int result4 = Task.Factory.StartNew (() => TaskMethodReturn("Task 4")).Result; //Console.WriteLine($"Task 4 Result is:{result4}"); #endregion #region 測試Task線程是來自于ThreadPool // Test(); #endregion // 合作開發(fā)項(xiàng)目,每個(gè)人負(fù)責(zé)一個(gè)模塊,可以認(rèn)為是多線程 Console.WriteLine("開始合作開發(fā)一個(gè)大項(xiàng)目!"); Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!")); Task.Run(() => CodingShow("Kevin", "微信接口!")); Task.Run(() => CodingShow("Jack", "搭建后臺(tái)框架!")); Task.Run(() => CodingShow("Alex", "設(shè)計(jì)數(shù)據(jù)庫!")); Task.Run(() => CodingShow("Lee", "支付寶接口對接!")); Console.ReadKey(); } /// /// 返回一個(gè)Task /// ////// static Task CreateTask(string name) { // 參數(shù)是Func return new Task (() => TaskMethodReturn(name)); } static void TaskMethod(string name) { Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}", name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); } static int TaskMethodReturn(string name) { Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}", name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); Thread.Sleep(TimeSpan.FromSeconds(2)); return 42; } /// /// 測試Task的線程來自于ThreadPool /// static void Test() { // 設(shè)置線程池中最大的線程數(shù) ThreadPool.SetMaxThreads(6, 6); // 創(chuàng)建Task的集合 ListtaskList = new List (); // 創(chuàng)建int類型的集合,用于存放線程ID List threadIdList = new List (); // 使用Task循環(huán)創(chuàng)建50個(gè)線程 for (int i = 0; i < 30; i++) { int k = i; Task task = Task.Run(() => { // 當(dāng)前線程ID加入到集合中 threadIdList.Add(Thread.CurrentThread.ManagedThreadId); Console.WriteLine($"this is {k} 循環(huán) ThreadID:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"); // 休眠 Thread.Sleep(200); }); // 把task加入到集合中 taskList.Add(task); } // 等待所有的線程執(zhí)行完 Task.WaitAll(taskList.ToArray()); // 輸出總數(shù)量 Console.WriteLine($"線程總數(shù):{threadIdList.Distinct().Count()}"); } /// /// 模擬Coding過程 /// /// /// static void CodingShow(string name, string projectName) { Console.WriteLine($"CodingShow Start {name} {projectName} {Thread.CurrentThread.ManagedThreadId.ToString("00")} "); long lResult = 0; for (int i = 0; i < 1_000_000_000; i++) { lResult += i; } Console.WriteLine($"CodingShow End {name} {projectName} {Thread.CurrentThread.ManagedThreadId.ToString("00")} "); } } }
程序運(yùn)行結(jié)果:
這時(shí)需求發(fā)生了變化,所有的模塊都開發(fā)完成以后,開始搭建測試環(huán)境,修改代碼如下:
// 合作開發(fā)項(xiàng)目,每個(gè)人負(fù)責(zé)一個(gè)模塊,可以認(rèn)為是多線程 Console.WriteLine("開始合作開發(fā)一個(gè)大項(xiàng)目!"); Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!")); Task.Run(() => CodingShow("Kevin", "微信接口!")); Task.Run(() => CodingShow("Jack", "搭建后臺(tái)框架!")); Task.Run(() => CodingShow("Alex", "設(shè)計(jì)數(shù)據(jù)庫!")); Task.Run(() => CodingShow("Lee", "支付寶接口對接!")); Console.WriteLine("所有模塊都開發(fā)完成,開始搭建測試環(huán)境");
程序運(yùn)行結(jié)果:
可以看到顯然不是我們想要的結(jié)果,模塊開發(fā)工作還沒有結(jié)束就搭建測試環(huán)境,即子線程還沒有結(jié)束,主線程就已經(jīng)結(jié)束了。要想實(shí)現(xiàn)我們想要的效果,那么必須使主線程等待所有子線程都結(jié)束以后,主線程才能結(jié)束。
1、WaitAll()
WaitAll()表示等待所有的Task都執(zhí)行完成。看WaitAll()的定義:
WaitAll()方法有很多重載,我們在這里使用第一個(gè)重載方法,即參數(shù)是Task[]數(shù)組。查看Run()方法的定義時(shí),我們會(huì)發(fā)現(xiàn)Run()方法的返回值就是Task類型,我們使用WaitAll()修改上面的代碼:
// 定義一個(gè)Task類型的集合 ListtaskList = new List (); Console.WriteLine("開始合作開發(fā)一個(gè)大項(xiàng)目!"); taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!"))); taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!"))); taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后臺(tái)框架!"))); taskList.Add(Task.Run(() => CodingShow("Alex", "設(shè)計(jì)數(shù)據(jù)庫!"))); taskList.Add(Task.Run(() => CodingShow("Lee", "支付寶接口對接!"))); // 等待所有模塊都開發(fā)完成,才能搭建測試環(huán)境 Task.WaitAll(taskList.ToArray()); Console.WriteLine("所有模塊都開發(fā)完成,開始搭建測試環(huán)境");
程序運(yùn)行結(jié)果:
WaitAll()會(huì)使程序產(chǎn)生卡頓。
加載首頁信息的時(shí)候可以使用WaitAll()方法。一個(gè)首頁信息可能來自于幾部分的數(shù)據(jù),每一部分的數(shù)據(jù)對應(yīng)一個(gè)線程,只有所有的線程都執(zhí)行完畢才顯示首頁信息。
2、WaitAny()
這時(shí)需求又發(fā)生改變了:某一個(gè)模塊開發(fā)完成以后就搭建測試環(huán)境。這時(shí)候就可以使用WaitAny()了。WaitAny()表示等待其中任何一個(gè)任務(wù)完成就會(huì)進(jìn)入下一個(gè)任務(wù),定義如下:
修改后的代碼如下:
// 定義一個(gè)Task類型的集合 ListtaskList = new List (); Console.WriteLine("開始合作開發(fā)一個(gè)大項(xiàng)目!"); taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!"))); taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!"))); taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后臺(tái)框架!"))); taskList.Add(Task.Run(() => CodingShow("Alex", "設(shè)計(jì)數(shù)據(jù)庫!"))); taskList.Add(Task.Run(() => CodingShow("Lee", "支付寶接口對接!"))); // 等待所有模塊都開發(fā)完成,才能搭建測試環(huán)境 Task.WaitAny(taskList.ToArray()); Console.WriteLine("有模塊開發(fā)完成,開始搭建測試環(huán)境");
程序運(yùn)行結(jié)果:
可以看到:設(shè)計(jì)數(shù)據(jù)庫模塊完成以后,就開始搭建測試環(huán)境了。如何需求。
WaitAny()會(huì)使程序產(chǎn)生卡頓。
有一個(gè)列表數(shù)據(jù),數(shù)據(jù)可以來源于接口、緩存、數(shù)據(jù)庫等,可以開啟多個(gè)線程,只要有一個(gè)線程執(zhí)行完畢就可以繼續(xù)執(zhí)行下面的步驟,這時(shí)就可以使用WaitAny()。
3、ContinueWhenAll()
WaitAll()會(huì)卡頓界面,那么有沒有不卡頓界面的呢?ContinueWhenAll和WaitAll實(shí)現(xiàn)的效果一樣,代碼如下:
ListtaskList = new List (); Console.WriteLine("開始合作開發(fā)一個(gè)大項(xiàng)目!"); taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!"))); taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!"))); taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后臺(tái)框架!"))); taskList.Add(Task.Run(() => CodingShow("Alex", "設(shè)計(jì)數(shù)據(jù)庫!"))); taskList.Add(Task.Run(() => CodingShow("Lee", "支付寶接口對接!"))); TaskFactory factory = new TaskFactory(); factory.ContinueWhenAll(taskList.ToArray(), t => Console.WriteLine("所有模塊開發(fā)完成"));
程序運(yùn)行結(jié)果:
4、ContinueWhenAny
ContinueWhenAny實(shí)現(xiàn)的效果和WaitAny一樣,ContinueWhenAny不會(huì)卡頓界面,代碼如下:
ListtaskList = new List (); Console.WriteLine("開始合作開發(fā)一個(gè)大項(xiàng)目!"); taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!"))); taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!"))); taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后臺(tái)框架!"))); taskList.Add(Task.Run(() => CodingShow("Alex", "設(shè)計(jì)數(shù)據(jù)庫!"))); taskList.Add(Task.Run(() => CodingShow("Lee", "支付寶接口對接!"))); TaskFactory factory = new TaskFactory(); factory.ContinueWhenAny(taskList.ToArray(), t => Console.WriteLine("某一個(gè)模塊開發(fā)完成"));
程序運(yùn)行結(jié)果:
ContinueWhenAll()和ContinueWhenAny()都會(huì)開啟一個(gè)新的線程。
5、ContinueWith
ContinueWith表示回調(diào),代碼如下:
Task.Run(() => { Console.WriteLine("任務(wù)執(zhí)行完成"); }).ContinueWith(p=> { Task.Run(() => { Console.WriteLine("執(zhí)行回調(diào)"); }); });
程序執(zhí)行結(jié)果:
程序完整代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace TaskDemo { class Program { static void Main(string[] args) { #region 1、使用Task創(chuàng)建任務(wù) //Task task = new Task(() => TaskMethod("Task 1")); //Console.WriteLine("before start status:"+task.Status); //// Task創(chuàng)建的任務(wù)必須調(diào)用start方法才能啟動(dòng) //task.Start(); //Console.WriteLine("after start status:" + task.Status); #endregion #region 2、使用Task.Run創(chuàng)建任務(wù) // Task.Run(() => TaskMethod("Task Run")); #endregion #region 3、使用Factory創(chuàng)建任務(wù) // 使用Task.Factory創(chuàng)建 //Task.Factory.StartNew(() => TaskMethod("Task 4")); ////標(biāo)記為長時(shí)間運(yùn)行任務(wù),則任務(wù)不會(huì)使用線程池,而在單獨(dú)的線程中運(yùn)行。 //Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning); // 實(shí)例化TaskFactory對象,然后創(chuàng)建 //TaskFactory factory = new TaskFactory(); //factory.StartNew(() => TaskMethod("Task 6")); #endregion #region 4、創(chuàng)建帶返回值的任務(wù) //TaskMethodReturn("Main Thread Task"); //// 創(chuàng)建帶返回值的Task //Tasktask = CreateTask("Task 1"); //// 啟動(dòng) //task.Start(); //// 獲取返回值 //int result1 = task.Result; //Console.WriteLine($"Task 1 Result is:{result1}"); //Task task2 = new Task (() => TaskMethodReturn("Task 2")); //task2.Start(); //int result2 = task2.Result; //Console.WriteLine($"Task 2 Result is:{result2}"); //int result3= Task.Run (() => TaskMethodReturn("Task 3")).Result; //Console.WriteLine($"Task 3 Result is:{result3}"); //int result4 = Task.Factory.StartNew (() => TaskMethodReturn("Task 4")).Result; //Console.WriteLine($"Task 4 Result is:{result4}"); #endregion #region 測試Task線程是來自于ThreadPool // Test(); #endregion // 合作開發(fā)項(xiàng)目,每個(gè)人負(fù)責(zé)一個(gè)模塊,可以認(rèn)為是多線程 // 無序 //Console.WriteLine("開始合作開發(fā)一個(gè)大項(xiàng)目!"); //Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!")); //Task.Run(() => CodingShow("Kevin", "微信接口!")); //Task.Run(() => CodingShow("Jack", "搭建后臺(tái)框架!")); //Task.Run(() => CodingShow("Alex", "設(shè)計(jì)數(shù)據(jù)庫!")); //Task.Run(() => CodingShow("Lee", "支付寶接口對接!")); //Console.WriteLine("所有模塊都開發(fā)完成,開始搭建測試環(huán)境"); #region WaitAll //// 定義一個(gè)Task類型的集合 //List taskList = new List (); //Console.WriteLine("開始合作開發(fā)一個(gè)大項(xiàng)目!"); //taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!"))); //taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!"))); //taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后臺(tái)框架!"))); //taskList.Add(Task.Run(() => CodingShow("Alex", "設(shè)計(jì)數(shù)據(jù)庫!"))); //taskList.Add(Task.Run(() => CodingShow("Lee", "支付寶接口對接!"))); //// 等待所有模塊都開發(fā)完成,才能搭建測試環(huán)境 //Task.WaitAll(taskList.ToArray()); //Console.WriteLine("所有模塊都開發(fā)完成,開始搭建測試環(huán)境"); #endregion #region WaitAny // 定義一個(gè)Task類型的集合 //List taskList = new List (); //Console.WriteLine("開始合作開發(fā)一個(gè)大項(xiàng)目!"); //taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!"))); //taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!"))); //taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后臺(tái)框架!"))); //taskList.Add(Task.Run(() => CodingShow("Alex", "設(shè)計(jì)數(shù)據(jù)庫!"))); //taskList.Add(Task.Run(() => CodingShow("Lee", "支付寶接口對接!"))); //// 等待所有模塊都開發(fā)完成,才能搭建測試環(huán)境 //Task.WaitAny(taskList.ToArray()); //Console.WriteLine("有模塊開發(fā)完成,開始搭建測試環(huán)境"); #endregion #region ContinueWhenAll //List taskList = new List (); //Console.WriteLine("開始合作開發(fā)一個(gè)大項(xiàng)目!"); //taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!"))); //taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!"))); //taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后臺(tái)框架!"))); //taskList.Add(Task.Run(() => CodingShow("Alex", "設(shè)計(jì)數(shù)據(jù)庫!"))); //taskList.Add(Task.Run(() => CodingShow("Lee", "支付寶接口對接!"))); //TaskFactory factory = new TaskFactory(); //factory.ContinueWhenAll(taskList.ToArray(), t => Console.WriteLine("所有模塊開發(fā)完成")); #endregion #region ContinueWhenAll //List taskList = new List (); //Console.WriteLine("開始合作開發(fā)一個(gè)大項(xiàng)目!"); //taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服務(wù)架構(gòu)!"))); //taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!"))); //taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后臺(tái)框架!"))); //taskList.Add(Task.Run(() => CodingShow("Alex", "設(shè)計(jì)數(shù)據(jù)庫!"))); //taskList.Add(Task.Run(() => CodingShow("Lee", "支付寶接口對接!"))); //TaskFactory factory = new TaskFactory(); //factory.ContinueWhenAny(taskList.ToArray(), t => Console.WriteLine("某一個(gè)模塊開發(fā)完成")); #endregion #region ContinueWith Task.Run(() => { Console.WriteLine("任務(wù)執(zhí)行完成"); }).ContinueWith(p=> { Task.Run(() => { Console.WriteLine("執(zhí)行回調(diào)"); }); }); #endregion Console.ReadKey(); } /// /// 返回一個(gè)Task /// ////// static Task CreateTask(string name) { // 參數(shù)是Func return new Task (() => TaskMethodReturn(name)); } static void TaskMethod(string name) { Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}", name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); } static int TaskMethodReturn(string name) { Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}", name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); Thread.Sleep(TimeSpan.FromSeconds(2)); return 42; } /// /// 測試Task的線程來自于ThreadPool /// static void Test() { // 設(shè)置線程池中最大的線程數(shù) ThreadPool.SetMaxThreads(6, 6); // 創(chuàng)建Task的集合 ListtaskList = new List (); // 創(chuàng)建int類型的集合,用于存放線程ID List threadIdList = new List (); // 使用Task循環(huán)創(chuàng)建50個(gè)線程 for (int i = 0; i < 30; i++) { int k = i; Task task = Task.Run(() => { // 當(dāng)前線程ID加入到集合中 threadIdList.Add(Thread.CurrentThread.ManagedThreadId); Console.WriteLine($"this is {k} 循環(huán) ThreadID:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"); // 休眠 Thread.Sleep(200); }); // 把task加入到集合中 taskList.Add(task); } // 等待所有的線程執(zhí)行完 Task.WaitAll(taskList.ToArray()); // 輸出總數(shù)量 Console.WriteLine($"線程總數(shù):{threadIdList.Distinct().Count()}"); } /// /// 模擬Coding過程 /// /// /// static void CodingShow(string name, string projectName) { Console.WriteLine($"CodingShow Start {name} {projectName} {Thread.CurrentThread.ManagedThreadId.ToString("00")} "); long lResult = 0; for (int i = 0; i < 1_000_000_000; i++) { lResult += i; } Console.WriteLine($"CodingShow End {name} {projectName} {Thread.CurrentThread.ManagedThreadId.ToString("00")} "); } } }
原文鏈接:https://www.cnblogs.com/dotnet261010/p/12022290.html
相關(guān)推薦
- 2023-10-27 獲取html中元素的寬高
- 2022-11-04 C#使用BinaryFormatter類、ISerializable接口、XmlSerializer
- 2023-03-15 React受控組件與非受控組件實(shí)例分析講解_React
- 2023-05-30 C++中map和set的使用詳細(xì)攻略_C 語言
- 2022-10-26 Python?Pyinstaller庫安裝步驟以及使用方法_python
- 2023-01-02 GO比較兩個(gè)對象是否相同實(shí)戰(zhàn)案例_Golang
- 2022-09-26 Python?Celery定時(shí)任務(wù)詳細(xì)講解_python
- 2022-04-25 ASP.NET?Core?MVC中過濾器工作原理介紹_實(shí)用技巧
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支