C#多线程编程Task用法详解
一、基本概念
Task优势
ThreadPool相比Thread来说具备了很多优势,但是ThreadPool却又存在一些使用上的不方便,例如:
- ThreadPool不支持线程的取消、完成、失败通知等交互性操作;
- ThreadPool不支持线程执行的先后次序;
.NET Framework 在4.0的时候提供了一个功能更强大的概念:Task。Task在ThreadPool的基础上进行了优化,并提供了更多的API。看下面一个简单的示例:
using System; using System.Threading; using System.Threading.Tasks; namespace TaskDemo { class Program { static void Main(string[] args) { // 创建Task Task t = new Task(() => { Console.WriteLine("任务开始工作....."); Thread.Sleep(5000); }); // 启动 t.Start(); t.ContinueWith((task) => { Console.WriteLine("任务完成,完成时候的状态为:"); Console.WriteLine("IsCanceled={0}\tIsCompleted={1}\tIsFaulted={2}", task.IsCanceled, task.IsCompleted, task.IsFaulted); }); Console.WriteLine("启动"); Console.ReadKey(); } } }
二、Task用法
创建任务
Task创建的任务可以分为有返回值和无返回值两种。
1、使用Task创建无返回值
先看一下Task的定义:
可以看到Task构造函数的参数是Action委托。所以使用Task创建任务的代码如下:
using System; using System.Threading; using System.Threading.Tasks; namespace TaskDemo { class Program { static void Main(string[] args) { #region 1、使用Task创建任务 Task task = new Task(() => TaskMethod("Task 1")); Console.WriteLine("before start status:"+task.Status); // Task创建的任务必须调用start方法才能启动 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); } } }
程序运行结果:
注:任务的状态,Start之前为Created,Start之后为WaitingToRun。
2、使用Task.Run方法创建任务
Task.Run创建的任务可以执行启动:
using System; using System.Threading; using System.Threading.Tasks; namespace TaskDemo { class Program { static void Main(string[] args) { #region 1、使用Task创建任务 //Task task = new Task(() => TaskMethod("Task 1")); //Console.WriteLine("before start status:"+task.Status); //// Task创建的任务必须调用start方法才能启动 //task.Start(); //Console.WriteLine("after start status:" + task.Status); #endregion #region 2、使用Task.Run创建任务 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); } } }
程序运行结果:
3、使用Factory方式创建任务
using System; using System.Threading; using System.Threading.Tasks; namespace TaskDemo { class Program { static void Main(string[] args) { #region 1、使用Task创建任务 //Task task = new Task(() => TaskMethod("Task 1")); //Console.WriteLine("before start status:"+task.Status); //// Task创建的任务必须调用start方法才能启动 //task.Start(); //Console.WriteLine("after start status:" + task.Status); #endregion #region 2、使用Task.Run创建任务 // Task.Run(() => TaskMethod("Task Run")); #endregion #region 3、使用Factory创建任务 // 使用Task.Factory创建 Task.Factory.StartNew(() => TaskMethod("Task 4")); //标记为长时间运行任务,则任务不会使用线程池,而在单独的线程中运行。 Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning); // 实例化TaskFactory对象,然后创建 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); } } }
程序运行结果:
4、创建带返回值的Task
代码如下:
using System; using System.Threading; using System.Threading.Tasks; namespace TaskDemo { class Program { static void Main(string[] args) { #region 1、使用Task创建任务 //Task task = new Task(() => TaskMethod("Task 1")); //Console.WriteLine("before start status:"+task.Status); //// Task创建的任务必须调用start方法才能启动 //task.Start(); //Console.WriteLine("after start status:" + task.Status); #endregion #region 2、使用Task.Run创建任务 // Task.Run(() => TaskMethod("Task Run")); #endregion #region 3、使用Task.Factory创建任务 //Task.Factory.StartNew(() => TaskMethod("Task 4")); ////标记为长时间运行任务,则任务不会使用线程池,而在单独的线程中运行。 //Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning); #endregion #region 4、创建带返回值的任务 TaskMethodReturn("Main Thread Task"); // 创建带返回值的Task Task<int> task = CreateTask("Task 1"); // 启动 task.Start(); // 获取返回值 int result1 = task.Result; Console.WriteLine($"Task 1 Result is:{result1}"); Task<int> task2 = new Task<int>(() => TaskMethodReturn("Task 2")); task2.Start(); int result2 = task2.Result; Console.WriteLine($"Task 2 Result is:{result2}"); int result3= Task.Run<int>(() => TaskMethodReturn("Task 3")).Result; Console.WriteLine($"Task 3 Result is:{result3}"); int result4 = Task.Factory.StartNew<int>(() => TaskMethodReturn("Task 4")).Result; Console.WriteLine($"Task 4 Result is:{result4}"); #endregion Console.ReadKey(); } /// <summary> /// 返回一个Task<int> /// </summary> /// <param name="name"></param> /// <returns></returns> static Task<int> CreateTask(string name) { // 参数是Func<int> return new Task<int>(() => 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的,那么怎么证明呢?看下面的代码:
/// <summary> /// 测试Task的线程来自于ThreadPool /// </summary> static void Test() { // 设置线程池中最大的线程数 ThreadPool.SetMaxThreads(6, 6); // 创建Task的集合 List<Task> taskList = new List<Task>(); // 创建int类型的集合,用于存放线程ID List<int> threadIdList = new List<int>(); // 使用Task循环创建50个线程 for (int i = 0; i < 30; i++) { int k = i; Task task = Task.Run(() => { // 当前线程ID加入到集合中 threadIdList.Add(Thread.CurrentThread.ManagedThreadId); Console.WriteLine($"this is {k} 循环 ThreadID:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"); // 休眠 Thread.Sleep(200); }); // 把task加入到集合中 taskList.Add(task); } // 等待所有的线程执行完 Task.WaitAll(taskList.ToArray()); // 输出总数量 Console.WriteLine($"线程总数:{threadIdList.Distinct().Count()}"); }
程序运行结果:
从结果中可以看出,Task中的线程确实是来自于ThreadPool。
三、常见方法
我们以下面的一个例子来讲解Task中比较常见的几个方法。多名开发者合作开发一个项目,每个人负责一个模块的开发,我们可以把这个过程认为是多线程,代码如下:
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创建任务 //Task task = new Task(() => TaskMethod("Task 1")); //Console.WriteLine("before start status:"+task.Status); //// Task创建的任务必须调用start方法才能启动 //task.Start(); //Console.WriteLine("after start status:" + task.Status); #endregion #region 2、使用Task.Run创建任务 // Task.Run(() => TaskMethod("Task Run")); #endregion #region 3、使用Factory创建任务 // 使用Task.Factory创建 //Task.Factory.StartNew(() => TaskMethod("Task 4")); ////标记为长时间运行任务,则任务不会使用线程池,而在单独的线程中运行。 //Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning); // 实例化TaskFactory对象,然后创建 //TaskFactory factory = new TaskFactory(); //factory.StartNew(() => TaskMethod("Task 6")); #endregion #region 4、创建带返回值的任务 //TaskMethodReturn("Main Thread Task"); //// 创建带返回值的Task //Task<int> task = CreateTask("Task 1"); //// 启动 //task.Start(); //// 获取返回值 //int result1 = task.Result; //Console.WriteLine($"Task 1 Result is:{result1}"); //Task<int> task2 = new Task<int>(() => TaskMethodReturn("Task 2")); //task2.Start(); //int result2 = task2.Result; //Console.WriteLine($"Task 2 Result is:{result2}"); //int result3= Task.Run<int>(() => TaskMethodReturn("Task 3")).Result; //Console.WriteLine($"Task 3 Result is:{result3}"); //int result4 = Task.Factory.StartNew<int>(() => TaskMethodReturn("Task 4")).Result; //Console.WriteLine($"Task 4 Result is:{result4}"); #endregion #region 测试Task线程是来自于ThreadPool // Test(); #endregion // 合作开发项目,每个人负责一个模块,可以认为是多线程 Console.WriteLine("开始合作开发一个大项目!"); Task.Run(() => CodingShow("Tom", "搭建微服务架构!")); Task.Run(() => CodingShow("Kevin", "微信接口!")); Task.Run(() => CodingShow("Jack", "搭建后台框架!")); Task.Run(() => CodingShow("Alex", "设计数据库!")); Task.Run(() => CodingShow("Lee", "支付宝接口对接!")); Console.ReadKey(); } /// <summary> /// 返回一个Task<int> /// </summary> /// <param name="name"></param> /// <returns></returns> static Task<int> CreateTask(string name) { // 参数是Func<int> return new Task<int>(() => 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; } /// <summary> /// 测试Task的线程来自于ThreadPool /// </summary> static void Test() { // 设置线程池中最大的线程数 ThreadPool.SetMaxThreads(6, 6); // 创建Task的集合 List<Task> taskList = new List<Task>(); // 创建int类型的集合,用于存放线程ID List<int> threadIdList = new List<int>(); // 使用Task循环创建50个线程 for (int i = 0; i < 30; i++) { int k = i; Task task = Task.Run(() => { // 当前线程ID加入到集合中 threadIdList.Add(Thread.CurrentThread.ManagedThreadId); Console.WriteLine($"this is {k} 循环 ThreadID:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"); // 休眠 Thread.Sleep(200); }); // 把task加入到集合中 taskList.Add(task); } // 等待所有的线程执行完 Task.WaitAll(taskList.ToArray()); // 输出总数量 Console.WriteLine($"线程总数:{threadIdList.Distinct().Count()}"); } /// <summary> /// 模拟Coding过程 /// </summary> /// <param name="name"></param> /// <param name="projectName"></param> 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")} "); } } }
程序运行结果:
这时需求发生了变化,所有的模块都开发完成以后,开始搭建测试环境,修改代码如下:
// 合作开发项目,每个人负责一个模块,可以认为是多线程 Console.WriteLine("开始合作开发一个大项目!"); Task.Run(() => CodingShow("Tom", "搭建微服务架构!")); Task.Run(() => CodingShow("Kevin", "微信接口!")); Task.Run(() => CodingShow("Jack", "搭建后台框架!")); Task.Run(() => CodingShow("Alex", "设计数据库!")); Task.Run(() => CodingShow("Lee", "支付宝接口对接!")); Console.WriteLine("所有模块都开发完成,开始搭建测试环境");
程序运行结果:
可以看到显然不是我们想要的结果,模块开发工作还没有结束就搭建测试环境,即子线程还没有结束,主线程就已经结束了。要想实现我们想要的效果,那么必须使主线程等待所有子线程都结束以后,主线程才能结束。
1、WaitAll()
WaitAll()表示等待所有的Task都执行完成。看WaitAll()的定义:
WaitAll()方法有很多重载,我们在这里使用第一个重载方法,即参数是Task[]数组。查看Run()方法的定义时,我们会发现Run()方法的返回值就是Task类型,我们使用WaitAll()修改上面的代码:
// 定义一个Task类型的集合 List<Task> taskList = new List<Task>(); Console.WriteLine("开始合作开发一个大项目!"); taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服务架构!"))); taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!"))); taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后台框架!"))); taskList.Add(Task.Run(() => CodingShow("Alex", "设计数据库!"))); taskList.Add(Task.Run(() => CodingShow("Lee", "支付宝接口对接!"))); // 等待所有模块都开发完成,才能搭建测试环境 Task.WaitAll(taskList.ToArray()); Console.WriteLine("所有模块都开发完成,开始搭建测试环境");
程序运行结果:
WaitAll()会使程序产生卡顿。
加载首页信息的时候可以使用WaitAll()方法。一个首页信息可能来自于几部分的数据,每一部分的数据对应一个线程,只有所有的线程都执行完毕才显示首页信息。
2、WaitAny()
这时需求又发生改变了:某一个模块开发完成以后就搭建测试环境。这时候就可以使用WaitAny()了。WaitAny()表示等待其中任何一个任务完成就会进入下一个任务,定义如下:
修改后的代码如下:
// 定义一个Task类型的集合 List<Task> taskList = new List<Task>(); Console.WriteLine("开始合作开发一个大项目!"); taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服务架构!"))); taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!"))); taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后台框架!"))); taskList.Add(Task.Run(() => CodingShow("Alex", "设计数据库!"))); taskList.Add(Task.Run(() => CodingShow("Lee", "支付宝接口对接!"))); // 等待所有模块都开发完成,才能搭建测试环境 Task.WaitAny(taskList.ToArray()); Console.WriteLine("有模块开发完成,开始搭建测试环境");
程序运行结果:
可以看到:设计数据库模块完成以后,就开始搭建测试环境了。如何需求。
WaitAny()会使程序产生卡顿。
有一个列表数据,数据可以来源于接口、缓存、数据库等,可以开启多个线程,只要有一个线程执行完毕就可以继续执行下面的步骤,这时就可以使用WaitAny()。
3、ContinueWhenAll()
WaitAll()会卡顿界面,那么有没有不卡顿界面的呢?ContinueWhenAll和WaitAll实现的效果一样,代码如下:
List<Task> taskList = new List<Task>(); Console.WriteLine("开始合作开发一个大项目!"); taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服务架构!"))); taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!"))); taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后台框架!"))); taskList.Add(Task.Run(() => CodingShow("Alex", "设计数据库!"))); taskList.Add(Task.Run(() => CodingShow("Lee", "支付宝接口对接!"))); TaskFactory factory = new TaskFactory(); factory.ContinueWhenAll(taskList.ToArray(), t => Console.WriteLine("所有模块开发完成"));
程序运行结果:
4、ContinueWhenAny
ContinueWhenAny实现的效果和WaitAny一样,ContinueWhenAny不会卡顿界面,代码如下:
List<Task> taskList = new List<Task>(); Console.WriteLine("开始合作开发一个大项目!"); taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服务架构!"))); taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!"))); taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后台框架!"))); taskList.Add(Task.Run(() => CodingShow("Alex", "设计数据库!"))); taskList.Add(Task.Run(() => CodingShow("Lee", "支付宝接口对接!"))); TaskFactory factory = new TaskFactory(); factory.ContinueWhenAny(taskList.ToArray(), t => Console.WriteLine("某一个模块开发完成"));
程序运行结果:
ContinueWhenAll()和ContinueWhenAny()都会开启一个新的线程。
5、ContinueWith
ContinueWith表示回调,代码如下:
Task.Run(() => { Console.WriteLine("任务执行完成"); }).ContinueWith(p=> { Task.Run(() => { Console.WriteLine("执行回调"); }); });
程序执行结果:
程序完整代码如下:
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创建任务 //Task task = new Task(() => TaskMethod("Task 1")); //Console.WriteLine("before start status:"+task.Status); //// Task创建的任务必须调用start方法才能启动 //task.Start(); //Console.WriteLine("after start status:" + task.Status); #endregion #region 2、使用Task.Run创建任务 // Task.Run(() => TaskMethod("Task Run")); #endregion #region 3、使用Factory创建任务 // 使用Task.Factory创建 //Task.Factory.StartNew(() => TaskMethod("Task 4")); ////标记为长时间运行任务,则任务不会使用线程池,而在单独的线程中运行。 //Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning); // 实例化TaskFactory对象,然后创建 //TaskFactory factory = new TaskFactory(); //factory.StartNew(() => TaskMethod("Task 6")); #endregion #region 4、创建带返回值的任务 //TaskMethodReturn("Main Thread Task"); //// 创建带返回值的Task //Task<int> task = CreateTask("Task 1"); //// 启动 //task.Start(); //// 获取返回值 //int result1 = task.Result; //Console.WriteLine($"Task 1 Result is:{result1}"); //Task<int> task2 = new Task<int>(() => TaskMethodReturn("Task 2")); //task2.Start(); //int result2 = task2.Result; //Console.WriteLine($"Task 2 Result is:{result2}"); //int result3= Task.Run<int>(() => TaskMethodReturn("Task 3")).Result; //Console.WriteLine($"Task 3 Result is:{result3}"); //int result4 = Task.Factory.StartNew<int>(() => TaskMethodReturn("Task 4")).Result; //Console.WriteLine($"Task 4 Result is:{result4}"); #endregion #region 测试Task线程是来自于ThreadPool // Test(); #endregion // 合作开发项目,每个人负责一个模块,可以认为是多线程 // 无序 //Console.WriteLine("开始合作开发一个大项目!"); //Task.Run(() => CodingShow("Tom", "搭建微服务架构!")); //Task.Run(() => CodingShow("Kevin", "微信接口!")); //Task.Run(() => CodingShow("Jack", "搭建后台框架!")); //Task.Run(() => CodingShow("Alex", "设计数据库!")); //Task.Run(() => CodingShow("Lee", "支付宝接口对接!")); //Console.WriteLine("所有模块都开发完成,开始搭建测试环境"); #region WaitAll //// 定义一个Task类型的集合 //List<Task> taskList = new List<Task>(); //Console.WriteLine("开始合作开发一个大项目!"); //taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服务架构!"))); //taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!"))); //taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后台框架!"))); //taskList.Add(Task.Run(() => CodingShow("Alex", "设计数据库!"))); //taskList.Add(Task.Run(() => CodingShow("Lee", "支付宝接口对接!"))); //// 等待所有模块都开发完成,才能搭建测试环境 //Task.WaitAll(taskList.ToArray()); //Console.WriteLine("所有模块都开发完成,开始搭建测试环境"); #endregion #region WaitAny // 定义一个Task类型的集合 //List<Task> taskList = new List<Task>(); //Console.WriteLine("开始合作开发一个大项目!"); //taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服务架构!"))); //taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!"))); //taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后台框架!"))); //taskList.Add(Task.Run(() => CodingShow("Alex", "设计数据库!"))); //taskList.Add(Task.Run(() => CodingShow("Lee", "支付宝接口对接!"))); //// 等待所有模块都开发完成,才能搭建测试环境 //Task.WaitAny(taskList.ToArray()); //Console.WriteLine("有模块开发完成,开始搭建测试环境"); #endregion #region ContinueWhenAll //List<Task> taskList = new List<Task>(); //Console.WriteLine("开始合作开发一个大项目!"); //taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服务架构!"))); //taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!"))); //taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后台框架!"))); //taskList.Add(Task.Run(() => CodingShow("Alex", "设计数据库!"))); //taskList.Add(Task.Run(() => CodingShow("Lee", "支付宝接口对接!"))); //TaskFactory factory = new TaskFactory(); //factory.ContinueWhenAll(taskList.ToArray(), t => Console.WriteLine("所有模块开发完成")); #endregion #region ContinueWhenAll //List<Task> taskList = new List<Task>(); //Console.WriteLine("开始合作开发一个大项目!"); //taskList.Add(Task.Run(() => CodingShow("Tom", "搭建微服务架构!"))); //taskList.Add(Task.Run(() => CodingShow("Kevin", "微信接口!"))); //taskList.Add(Task.Run(() => CodingShow("Jack", "搭建后台框架!"))); //taskList.Add(Task.Run(() => CodingShow("Alex", "设计数据库!"))); //taskList.Add(Task.Run(() => CodingShow("Lee", "支付宝接口对接!"))); //TaskFactory factory = new TaskFactory(); //factory.ContinueWhenAny(taskList.ToArray(), t => Console.WriteLine("某一个模块开发完成")); #endregion #region ContinueWith Task.Run(() => { Console.WriteLine("任务执行完成"); }).ContinueWith(p=> { Task.Run(() => { Console.WriteLine("执行回调"); }); }); #endregion Console.ReadKey(); } /// <summary> /// 返回一个Task<int> /// </summary> /// <param name="name"></param> /// <returns></returns> static Task<int> CreateTask(string name) { // 参数是Func<int> return new Task<int>(() => 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; } /// <summary> /// 测试Task的线程来自于ThreadPool /// </summary> static void Test() { // 设置线程池中最大的线程数 ThreadPool.SetMaxThreads(6, 6); // 创建Task的集合 List<Task> taskList = new List<Task>(); // 创建int类型的集合,用于存放线程ID List<int> threadIdList = new List<int>(); // 使用Task循环创建50个线程 for (int i = 0; i < 30; i++) { int k = i; Task task = Task.Run(() => { // 当前线程ID加入到集合中 threadIdList.Add(Thread.CurrentThread.ManagedThreadId); Console.WriteLine($"this is {k} 循环 ThreadID:{Thread.CurrentThread.ManagedThreadId.ToString("00")}"); // 休眠 Thread.Sleep(200); }); // 把task加入到集合中 taskList.Add(task); } // 等待所有的线程执行完 Task.WaitAll(taskList.ToArray()); // 输出总数量 Console.WriteLine($"线程总数:{threadIdList.Distinct().Count()}"); } /// <summary> /// 模拟Coding过程 /// </summary> /// <param name="name"></param> /// <param name="projectName"></param> 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")} "); } } }
到此这篇关于C#多线程编程Task用法的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
最新评论