[.NetCore视频随手码]3.异步编程背后的线程切换

  • Post author:
  • Post category:其他


        static async Task Main(string[] args)
        {
            using (HttpClient httpClient = new HttpClient())
            {
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId); 
                var html = await httpClient.GetStringAsync("https://www.jd.com/");
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
            }
        }

通过Console.WriteLine(Thread.CurrentThread.ManagedThreadId); 可以在控制台输出线程Id。运行结果如下:

结论:线程Id发生了改变,也就是说两次完成两次输出时占用的不是同一个线程。

原因:await调用的等待期间,.Net会把当前的线程返还给线程池,当异步方法执行完毕后,框架会从线程池再取出来一个线程执行后续的代码。类似于去餐厅吃饭,进餐厅时为我们点菜的是服务员A,点完菜时,服务员A去服务其他客人了。到菜做好了,传菜的是服务员B了。

当然如果你点的是米饭,可能递给你得依旧是服务员A。异步方法如果不是特别耗时的操作,那么使用的还是同一个线程,例子如下:

            using (HttpClient httpClient = new HttpClient())
            {
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
                //var html = await httpClient.GetStringAsync("https://www.jd.com/");

                string content = await File.ReadAllTextAsync("../Resource/1.txt");
                Console.WriteLine("文件内容" + content);

                Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
            }

执行的结果如下:

原理:此处为CLR的优化,当要等待的时候发现已经执行结束,那么就没有必要切换线程了,剩下的代码继续在当前线程上执行。



版权声明:本文为weixin_42765260原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。