多线程
线程概念
- 线程
- 进程想要执行任务就需要依赖线程。换句话说,就是进程中的最小执行单位就是线程,并且一个进程中至少有一个线程
- 前台线程/后台线程
- 结束进程时,需要等前台线程结束,才能完全结束,而后台线程会在进程结束时同时结束
Thread
- 默认前台线程
- 有线程的取消、完成、失败通知等交互性操作
- 通过jion阻塞,达到线程执行的先后次序
ThreadPool
- 默认后台线程
- 无线程的取消、完成、失败通知等交互性操作
- 可以减少每次创建线程的开销
static void Main(string[] args)
{
ThreadPool.SetMinThreads(12, 12);
for (int i = 0; i < 10; i++)
{
int k = i;
ThreadPool.QueueUserWorkItem(GetThreadPool, i);
}
//Console.WriteLine($"主线程执行完毕!{DateTime.Now}");
Console.Read();
}
static void GetThreadPool(object index)
{
Thread.Sleep(1000);
Console.WriteLine($"异步运行,第{index}个{DateTime.Now}");
}
返回
异步运行,第0个2021/01/26 15:37:49
异步运行,第2个2021/01/26 15:37:49
异步运行,第7个2021/01/26 15:37:49
异步运行,第8个2021/01/26 15:37:49
异步运行,第9个2021/01/26 15:37:49
异步运行,第1个2021/01/26 15:37:49
异步运行,第6个2021/01/26 15:37:49
异步运行,第4个2021/01/26 15:37:49
异步运行,第3个2021/01/26 15:37:49
异步运行,第5个2021/01/26 15:37:49
可以通过SetMaxThreads来设置一次性最大创建多少个线程,如Max为8,上面就会分两次返回结果的,但Max值不能小于当前服务器最低的线程数,也可以设置SetMinThreads数来设置当前最低线程数,同样不能低于服务器实际最低线程数
ThreadPool.SetMaxThreads(8, 8);
返回
异步运行,第3个2021/01/26 15:41:02
异步运行,第2个2021/01/26 15:41:02
异步运行,第1个2021/01/26 15:41:02
异步运行,第0个2021/01/26 15:41:02
异步运行,第5个2021/01/26 15:41:02
异步运行,第6个2021/01/26 15:41:02
异步运行,第4个2021/01/26 15:41:02
异步运行,第7个2021/01/26 15:41:02
异步运行,第8个2021/01/26 15:41:03
异步运行,第9个2021/01/26 15:41:03
异步
Task
异步和同步
- 发起一个请求,等待到它运行完成即为同步
- 发起一个请求,不等待结果,可以先去执行后面的业务,即为异步
异步调用方式
Task task1 = new Task(()=>{
Console.WriteLine("异步运行1");
});
task1.Start();
Task task2 = Task.Factory.StartNew(()=>{
Console.WriteLine("异步运行2");
});
Task task3 = Task.Run(()=>{
Console.WriteLine("异步运行3");
});
异步完成
static void Main(string[] args)
{
Task<string> task = new Task<string>(() =>
{
Console.WriteLine($"异步运行");
return "123";
});
task.Start();
task.ContinueWith(t => {
Console.WriteLine($"异步完成,{t.Result}");
});
Console.WriteLine($"异步开始");
Thread.Sleep(5 * 1000);
Console.Read();
}
返回结果
异步开始
异步运行
异步完成,123
扩展还可以使用
Task.WhenAll(task1, task2).ContinueWith((t) => {
Thread.Sleep(100);
Console.WriteLine("执行后续操作完毕!");
});
Task.WhenAny(task1, task2).ContinueWith((t) => {
Thread.Sleep(100);
Console.WriteLine("执行后续操作完毕!");
});
异步阻塞
正常代码
static void Main(string[] args)
{
Task<string> task1 = GetAwaitTask(1, "1");
Task<string> task2 = GetAwaitTask(2, "2");
Task<string> task3 = GetAwaitTask(1, "3");
Task<string> task4 = GetAwaitTask(1, "4");
//Task.WaitAll(new Task[] { task1, task2,task3,task4 });
Console.WriteLine($"主线程执行开始!{DateTime.Now}");
//Console.WriteLine($"主线程执行完毕!{DateTime.Now}");
Console.Read();
}
static Task<string> GetAwaitTask(int nMs, string index)
{
Task<string> task = Task.Run(() =>
{
Thread.Sleep(nMs * 1000);
Console.WriteLine($"异步运行,第{index}个{DateTime.Now}");
return $"ceshiyixia{index}";
});
Console.WriteLine($"异步开始,第{index}个{DateTime.Now}");
return task;
}
返回结果
异步开始,第1个2021/01/26 11:17:00
异步开始,第2个2021/01/26 11:17:00
异步开始,第3个2021/01/26 11:17:00
异步开始,第4个2021/01/26 11:17:00
主线程执行开始!2021/01/26 11:17:00
异步运行,第1个2021/01/26 11:17:01
异步运行,第3个2021/01/26 11:17:01
异步运行,第4个2021/01/26 11:17:01
异步运行,第2个2021/01/26 11:17:02
增加WaitAll后,返回
异步开始,第1个2021/01/26 11:17:49
异步开始,第2个2021/01/26 11:17:49
异步开始,第3个2021/01/26 11:17:49
异步开始,第4个2021/01/26 11:17:49
异步运行,第1个2021/01/26 11:17:50
异步运行,第3个2021/01/26 11:17:50
异步运行,第4个2021/01/26 11:17:50
异步运行,第2个2021/01/26 11:17:51
主线程执行开始!2021/01/26 11:17:51
增加WaitAny后
Task.WaitAny(new Task[] { task1, task2,task3,task4 });
返回
异步开始,第1个2021/01/26 11:18:22
异步开始,第2个2021/01/26 11:18:22
异步开始,第3个2021/01/26 11:18:22
异步开始,第4个2021/01/26 11:18:22
异步运行,第1个2021/01/26 11:18:23
主线程执行开始!2021/01/26 11:18:23
异步运行,第3个2021/01/26 11:18:23
异步运行,第4个2021/01/26 11:18:23
异步运行,第2个2021/01/26 11:18:24
async/await
static void Main(string[] args)
{
Console.WriteLine(GetAwaitTask(1,"1"))
Console.WriteLine(GetAwaitTask(2,"2"));
Console.WriteLine(GetAwaitTask(1,"3"));
Console.WriteLine(GetAwaitTask(1,"4"));
Console.WriteLine("主线程异步开始");
Thread.Sleep(5 * 1000);
Console.Read();
}
async static Task<string> GetAwaitTask(int nMs,string index)
{
string task = await Task.Run(() =>
{
Console.WriteLine($"异步运行,第{index}个{DateTime.Now}");
Thread.Sleep(nMs*1000);
return $"ceshiyixia{index}";
});
Console.WriteLine($"异步开始,第{index}个{DateTime.Now}");
return task;
}
返回结果
System.Threading.Tasks.Task`1[System.String]
System.Threading.Tasks.Task`1[System.String]
System.Threading.Tasks.Task`1[System.String]
System.Threading.Tasks.Task`1[System.String]
主线程异步开始
异步运行,第1个2021/01/26 10:54:09
异步运行,第3个2021/01/26 10:54:09
异步运行,第2个2021/01/26 10:54:09
异步运行,第4个2021/01/26 10:54:09
异步开始,第1个2021/01/26 10:54:10
异步开始,第3个2021/01/26 10:54:10
异步开始,第4个2021/01/26 10:54:10
异步开始,第2个2021/01/26 10:54:11
同样可以通过GetAwaitTask(1,“1”).Result的方式,阻塞,按顺序返回;