Wat*_* v2 3 .net c# asynchronous task-parallel-library async-await
两者之间的机械差异是什么?
async void LongIOBoundWorkWithSomeCPUBoundWorkAsWellAsync()
{
await Task.Run(CPUBoundWork);
// Do IO bound work
await DoIOAsync();
}
and
async void LongIOBoundWorkWithSomeCPUBoundWorkAsWellAsync()
{
var cpuTask = Task.Run(CPUBoundWork);
cpuTask.Wait();
// Do IO bound work
await DoIOAsync();
}
Run Code Online (Sandbox Code Playgroud)
我从逻辑上理解,两者都会产生相同的控制流.在这两种情况下,DoIOAsync
只有在CPUBoundWork
任务完成执行后才会调用该方法.
但是,在两种情况下,CPU任务的调度方面是否存在差异?
更新
请确认我对上述代码的未经教育的反思是否正确.
根据我的理解,await
解除了线程与线程上运行的任务之间的任何关联.虽然这对I/O请求非常有用,但由于您现在重新使用在网络驱动程序上阻止的I/O线程,因此您希望保持与CPU绑定工作的线程关联.
虽然等待破坏这种亲和力,Wait()
但我不确定但纯粹猜测的方法只是等待任务完成.如果任务尚未开始,则在当前线程上执行该任务.但是,如果任务早先已经开始,它会阻塞当前线程,将当前线程放在等待队列上,下一次执行Wait
被调用任务的线程到来并完成其工作时,它会发出信号等待线程和等待线程继续.因此,在调用时会保持任务的线程关联性Wait
.
当然,所有这些仅仅是猜测.我希望有人确认一下.
我的理解是等待解除线程与线程上运行的任务之间的任何关联.
不,这根本不会发生什么.
首先,await
没有任何东西可以运行,没有任何"预定".在你到达之前,调度(如果有的话)和正在运行(如果有的话)已经在进行中await
.
await
是一个"异步等待"; 也就是说,它异步等待任务完成."异步"在这里表示"不阻塞当前线程".
我有一个更详细的介绍async
,并await
在我的博客.
我从逻辑上理解,两者都会产生相同的控制流.
并不是的.在Wait
将阻止当前线程,而await
不会.
在这两种情况下,只有在CPUBoundWork任务完成执行后才会调用DoIOAsync方法.
这是对的.
但是,在两种情况下,CPU任务的调度方面是否存在差异?
不,在这两种情况下,调度都是通过Task.Run
,而不是Wait
或完成的await
.
虽然这对I/O请求非常有用,但由于您现在重新使用在网络驱动程序上阻止的I/O线程,因此您希望保持与CPU绑定工作的线程关联.
如果你想留在同一个线程,那么你就无法使用Task.Run
.你必须CPUBoundWork
直接打电话.
Wait()方法,我不确定,但纯粹猜测,只是等待任务完成.如果任务尚未开始,则在当前线程上执行该任务.
还有更多的东西.有时它会,有时它不会.在您发布的代码中,通常不会(因为CPUBoundWork
已经开始).
因此,在调用Wait时会保持对任务的线程关联.
同样,这是一种简化.如果通过"线程亲和力"表示线程在之前和之后是相同的Wait
,那么是的,这是正确的.
但是,在异步方法中阻塞任务可能很危险 ; 正如我在博客中描述的那样,你可以陷入僵局.如果你正在考虑使用Task.Run
与配合async
,请查看我的Task.Run
礼仪指导.