我正在尝试理解async/await模式的底层机制,读完以下杰尼弗·马斯曼(Jennifer Marsman)的博客文章《.NET 4.0中的工作窃取》后,我认为我已经理解了其中的核心。我的理解如下:
1 - 线程池有一个全局队列以及每个线程都有自己的本地队列。
2 - 请求进入全局队列,然后线程池中的线程1(T1)获取到请求。
3 - 这个请求是一个异步\等待方法。一旦遇到await关键字,就会创建一个包含书签(回调函数)的任务(假设该任务尚未完成),并将此任务放置在T1的本地队列中。T1返回到线程池。
4 - 当任务完成时,如果T1没有忙碌,T1将处理该请求。但是,如果T1忙碌,另一个线程(称之为T2)实际上可能从T1的本地队列中窃取此任务。
这就是我的问题所在。这怎么被禁止了呢?我读到的所有内容都表明,async\await不会改变线程上下文。请参见链接MSDN explanation of async\await。这也是有道理的,因为在MVC应用程序中,请求绑定到一个线程上。这意味着如果请求发送到异步操作方法,则我希望初始任务和后续任务都由同一个线程池线程完成。工作窃取线程怎么不会干扰这个呢?感谢任何见解。
1 - 线程池有一个全局队列以及每个线程都有自己的本地队列。
2 - 请求进入全局队列,然后线程池中的线程1(T1)获取到请求。
3 - 这个请求是一个异步\等待方法。一旦遇到await关键字,就会创建一个包含书签(回调函数)的任务(假设该任务尚未完成),并将此任务放置在T1的本地队列中。T1返回到线程池。
4 - 当任务完成时,如果T1没有忙碌,T1将处理该请求。但是,如果T1忙碌,另一个线程(称之为T2)实际上可能从T1的本地队列中窃取此任务。
这就是我的问题所在。这怎么被禁止了呢?我读到的所有内容都表明,async\await不会改变线程上下文。请参见链接MSDN explanation of async\await。这也是有道理的,因为在MVC应用程序中,请求绑定到一个线程上。这意味着如果请求发送到异步操作方法,则我希望初始任务和后续任务都由同一个线程池线程完成。工作窃取线程怎么不会干扰这个呢?感谢任何见解。
Task#ConfigureAwait(false)
来看,我认为异步/等待确实会改变其同步上下文。据我所知,ASP.NET 确实是一个特殊情况,但我不知道它是如何处理的。 - Jeroen Vannevel