2016-03-15 62 views
1

试想一个sitution当主叫用户创建一个任务:Task :: ConfigureAwait - 竞赛条件?

{ 
var tWithCapturedCtx = Task.Run(...); 
var tWithoutCapturedCtx = tWithCapturedCtx.ConfigureAwait(false); 

await tWithoutCapturedCtx; 
} 

有没有一种可能性,即tWithCapturedCtx将执行如此之快,将继续对所捕获的上下文中执行?

+2

您的编辑完全改变了问题,并可能使现有/接受的答案失效。请避免此类修改 - 如果您觉得您没有正确表达您的问题,请随时提出新问题。考虑恢复更改。 –

+0

@ user3284063:我回滚了你的编辑,因为它提出了一个不同的问题。请随时发布一个新问题。 –

回答

1

tWithCapturedCtx是否有可能执行得如此之快以至于继续将在捕获的上下文中执行?

的排序。

如果tWithCapturedCtx在评估await时已经完成(这意味着tWithoutCapturedCtx也已完成),则根本没有延续。 async方法只是继续同步执行(在相同的上下文中)。

然而,如果tWithCapturedCtx尚未由await被评估的时间完成(这意味着tWithoutCapturedCtx也不是已经完成),则继续被调度而不上下文被捕获。

await检查其等待时间是否完成以及await是否安排继续时,还有另一个甚至更小的竞态条件。如果在该窗口内等候完成,则继续只是同步运行(同样,在同一个上下文中)。

总之,ConfigureAwait(false)的意思是“我不在乎这个方法的其余部分在什么情况下运行”;它确实是而不是的意思是“在线程池中运行此方法的其余部分”。如果您想说“在线程池线程上运行此其他代码”,请使用Task.Run

+0

好的,谢谢。另一个问题:为什么他们不把continueOnCapturedContext参数放入Task :: Run方法的签名中?这样一来,最初的任务就可以用精确的知识来完成。 – user3284063

+0

@ user3284063:因为这不是任务的责任。只有*调用*代码知道它是否需要在捕获的上下文中恢复。它是“配置等待”,而不是“配置任务”。 –

+0

@StephenCleary侧注:OP编辑了我认为重大改变了这个问题的问题 - 请检查一下,看看是否应该回滚编辑(或者您可能想更新答案,我认为这会有点不对)。 –

0

ConfigureAwait正在被称为继续之前,甚至被添加到任务。继续被添加到被配置为不捕获上下文的对象,所以当继续运行时不会捕获上下文(这实际上是它存在的事情,它不会实现其记录的目的,如果它没有)。

+0

对不起,我不太清楚 - 请参阅更新后的问题 – user3284063