C#多线程编程Task用法详解

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

C#多线程编程Task⽤法详解
⽬录
⼀、基本概念
Task优势
⼆、Task⽤法
创建任务
1、使⽤Task创建⽆返回值
2、使⽤Task.Run⽅法创建任务
3、使⽤Factory⽅式创建任务
4、创建带返回值的Task
三、常见⽅法
1、WaitAll()
2、WaitAny()
3、ContinueWhenAll()
4、ContinueWhenAny
5、ContinueWith
⼀、基本概念
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⽤法的⽂章就介绍到这了。

希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。

相关文档
最新文档