11 async背后的线程切换

308 阅读1分钟

await调用的等待期间,.NET会把当前的线程返回给线程池,等异步方法调用执行完毕后,框架会从线程池再取出来一个线程执行后续的代码。

Thread.CurrentThread.ManagedThreadId获得当前线程Id。

验证:在耗时异步(写入大字符串)操作前后分别打印线程Id

1.长耗时

代码

using System.Text;

Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
StringBuilder s = new StringBuilder();

for (int i = 0; i < 10000; i++)
{
    s.Append("aaaaaaaaaa");
}

await File.WriteAllTextAsync("G:/1.txt",s.ToString());

Console.WriteLine(Thread.CurrentThread.ManagedThreadId);

结果

image.png

在运行长耗时下的线程情况:这里一开始线程id是1,在await后变成id是10,线程发生了切换。

2.短耗时

代码

using System.Text;

Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
StringBuilder s = new StringBuilder();

for (int i = 0; i < 10; i++)
{
    s.Append("aaaaaaaaaa");
}

await File.WriteAllTextAsync("G:/1.txt",s.ToString());

Console.WriteLine(Thread.CurrentThread.ManagedThreadId);

结果

image.png

在运行短耗时下的线程情况:将循环次数改为10次的结果,线程未发生切换。

总结

概述

在执行程序时会从线程池分配线程给程序,在遇到await时,线程不会一直等待异步任务完成,会把线程返回给线程池,在异步任务完成后,再分配一个线程给之后的程序代码,如果异步耗时较短,线程会不发生切换,因为这里与计算机的调度相关。到要等待的时候,如果发现已经执行结束了,那就没必要再切换线程了,剩下的代码就继续在之前的线程上继续执行了。

应用

在实际开发中,尽量避免发生线程切换,频繁切换会浪费资源,提高耗时

参考文献:blog.csdn.net/wsnbbdbbdbb…