1、遇到await,线程的变化
遇到await会把当前线程返回且返回值就是await后面的Task,再从线程池随机取一个线程往下执行代码。
我们使用封装好的异步方法模拟写入大量字符串的耗时操作:
static async Task Main(string[] args)
{
//原线程
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
//模拟写入大量字符串的耗时操作
StringBuilder str = new StringBuilder();
for (int i = 0; i < 1000; i++)
{
str.Append("Hello World!");
}
await File.WriteAllTextAsync(@"C:\Users\张跑跑\Desktop\net\async\1.txt", str.ToString());
//异步之后线程
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
}
结果显示前后线程不一致
那么问题来了,首先会随机到原来的线程吗?答案是会的,发生在异步操作所需时间很少的情况下。现在,我们仅仅把上述代码的循环次数缩短
static async Task Main(string[] args)
{
......
//降为10次
for (int i = 0; i < 10; i++)
{
str.Append("Hello World!");
}
......
}
可以看到,线程未改变。(作一个比喻就是,前台(当前线程)放你进店,服务员(新线程)把你领到座位上后忙自己的事,所以你点完菜可能是另一个服务员传,但服务员还没走远,你就点完了菜,那只好她继续上传菜单了)
参考:
https://zhuanlan.zhihu.com/p/343235838
https://www.cnblogs.com/jiangchengbiao/p/10040899.html
2、异步不等于多线程
自定义的异步方法并不会自动在新线程中执行,除非手动new线程、或者委托、或使用封装好的异步方法
我们模拟一个自定义异步方法
static async Task Main(string[] args)
{
//原线程
Console.WriteLine("原线程:" + Thread.CurrentThread.ManagedThreadId);
double r = await TestAsync();
Console.WriteLine(r);
//异步之后线程
Console.WriteLine("异步后线程:" + Thread.CurrentThread.ManagedThreadId);
}
static async Task<double> TestAsync()
{
//异步中线程
Console.WriteLine("异步后线程:" + Thread.CurrentThread.ManagedThreadId);
double n = 0;
Random random = new Random();
for (int i = 0; i < n * n; i++)
{
n = random.NextDouble();
}
return n;
}
结果是线程未改变
现在我们模拟一个委托
static async Task Main(string[] args)
{
//原线程
Console.WriteLine("原线程:" + Thread.CurrentThread.ManagedThreadId);
double r = await TestAsync1();
Console.WriteLine(r);
//异步之后线程
Console.WriteLine("异步后线程:" + Thread.CurrentThread.ManagedThreadId);
}
static async Task<double> TestAsync()
{
return await Task.Run(() =>
{
//异步中线程
Console.WriteLine("异步后线程:" + Thread.CurrentThread.ManagedThreadId);
double n = 0;
Random random = new Random();
for (int i = 0; i < n*n; i++)
{
n = random.NextDouble() ;
}
return n;
});
}
可以看到。此时的线程发生了改变
并且注意到,异步中和异步结束后的线程还是一致,前面提到是随机,难道真这么巧?在多次改变for的次数下,貌似不是随机的,难道除了自定义现在连委托也,但具体情况在我的认知盲区!!!我们知道切换线程是要消耗存在大量程序上下文开销,所以就猜想这是net给优化了吧
# async+await 和同步执行有什么好处,都是要一个线程干活,一条龙干到底不好吗,非得自己干到一半交给另一个线程去干,别人干活不用开销吗?
这个问题的关键就是有些IO事情真的不需要CPU派一个线程去干,去了也干不了。比如读写文件,以往同步方法时,派一个线程去读写点东西的时候,这个线程肯定是等在那的,读写这个事情是硬盘去做的,线程就是个使者,告诉硬盘要做哪些事就行,硬盘干完活就告诉线程,线程拿着结果开心地继续干下面的活。那异步就是线程通知硬盘去读写后自己就回去该干嘛干嘛去,不必等在硬盘家门口等消息。硬盘读写的时候,这个线程是非阻塞的,可以干其他活,提高效率。硬盘读写完,会通知CPU,叫他派一个线程来拿结果,(如果框架是单线程的,那还是这个线程过来)这个线程拿到结果后会继续执行之前那个线程未干完的活,至于上下文信息,底层会交代好,不在这里讨论,太深。这个IO事情有很多,比如访问数据库,请求网络等。
标签:异步,Task,Console,Thread,netcore,线程,WriteLine,多线程
From: https://www.cnblogs.com/long-live/p/aw.html