C# 为什么TPL在与continueOnCapturedContext一起使用Wait时不会死锁:true?
这个问题不同于其他问题。这个问题涉及一个案例,其中(据称)Wait导致死锁,而.Wait没有。这个问题正好相反。此外,问题和回答者在另一个问题上存在分歧,因此根本无法回答我的问题 这会导致ASP.Net请求上下文中出现死锁:C# 为什么TPL在与continueOnCapturedContext一起使用Wait时不会死锁:true?,c#,asynchronous,task-parallel-library,deadlock,C#,Asynchronous,Task Parallel Library,Deadlock,这个问题不同于其他问题。这个问题涉及一个案例,其中(据称)Wait导致死锁,而.Wait没有。这个问题正好相反。此外,问题和回答者在另一个问题上存在分歧,因此根本无法回答我的问题 这会导致ASP.Net请求上下文中出现死锁: protected void TestBtnClick(object sender, EventArgs e) { DoSomethingAsync() .Wait(); } private asy
protected void TestBtnClick(object sender, EventArgs e)
{
DoSomethingAsync()
.Wait();
}
private async Task DoSomethingAsync()
{
await Task.Delay(2000)
.ConfigureAwait(continueOnCapturedContext: true);
}
我的理解是,第一个调用方法正在等待整理原始同步上下文,然后被调用的方法也在等待整理原始上下文,从而导致死锁
如果是这种情况,为什么下面的操作不会导致死锁
protected async void TestBtnClickAsync(object sender, EventArgs e)
{
await DoSomethingAsync()
// ****** DIFFERENCE IS HERE: ******
.ConfigureAwait(continueOnCapturedContext: true);
}
private async Task DoSomethingAsync()
{
await Task.Delay(2000)
.ConfigureAwait(continueOnCapturedContext: true);
}
请注意,这两个异步调用都显式地请求在原始同步上下文上继续。因为在第一个代码块中,您显式地调用了
Wait()
。这会阻止线程的执行,因此无法在该线程上安排继续。线程永远不会返回池,它坐在那里等待一个信号继续执行,它永远不会收到这个信号,因为该信号将来自等待在等待线程上调度的延续
在第二个块中,
Wait
关键字将线程返回到池中,以便以后当线程空闲时(不处理其他请求),可以在该线程上再次安排继续操作。因为在第一个代码块中,您显式地调用了Wait()
。这会阻止线程的执行,因此无法在该线程上安排继续。线程永远不会返回池,它坐在那里等待一个信号继续执行,它永远不会收到这个信号,因为该信号将来自等待在等待线程上调度的延续
在第二个块中,
Wait
关键字将线程返回到池中,以便以后当线程空闲时(不处理其他请求),可以在该线程上再次安排继续操作。因为在第一个代码块中,您显式地调用了Wait()
。这会阻止线程的执行,因此无法在该线程上安排继续。线程永远不会返回池,它坐在那里等待一个信号继续执行,它永远不会收到这个信号,因为该信号将来自等待在等待线程上调度的延续
在第二个块中,
Wait
关键字将线程返回到池中,以便以后当线程空闲时(不处理其他请求),可以在该线程上再次安排继续操作。因为在第一个代码块中,您显式地调用了Wait()
。这会阻止线程的执行,因此无法在该线程上安排继续。线程永远不会返回池,它坐在那里等待一个信号继续执行,它永远不会收到这个信号,因为该信号将来自等待在等待线程上调度的延续
在第二个块中,
await
关键字将线程返回池中,以便以后当线程空闲时(不处理其他请求),可以在该线程上再次安排继续操作。在同一上下文中恢复大量等待的原因是,它们允许其他线程同时使用它
想象一下,在线程上执行就像那些“不得不握着棍子说话”组中的棍子一样。你的第一个例子是,一个人问某人一个问题,然后拒绝放弃棍子,直到问题得到回答。但另一个人在拿到棍子之前无法回答!显然这里会有问题
在你的第二个例子中,这个人问了某人一个问题,在给出答案后要求别人还给他棍子,然后放弃棍子。一路上可能会有一些无关的闲聊,但至少这个问题会得到回答。好多了
(请注意,默认情况下,在捕获的上下文上继续操作,因此您不会通过明确请求来更改任何内容。)在同一上下文上恢复大量等待的原因是,它们允许其他人同时使用它 想象一下,在线程上执行就像那些“不得不握着棍子说话”组中的棍子一样。你的第一个例子是,一个人问某人一个问题,然后拒绝放弃棍子,直到问题得到回答。但另一个人在拿到棍子之前无法回答!显然这里会有问题 在你的第二个例子中,这个人问了某人一个问题,在给出答案后要求别人还给他棍子,然后放弃棍子。一路上可能会有一些无关的闲聊,但至少这个问题会得到回答。好多了
(请注意,默认情况下,在捕获的上下文上继续操作,因此您不会通过明确请求来更改任何内容。)在同一上下文上恢复大量等待的原因是,它们允许其他人同时使用它 想象一下,在线程上执行就像那些“不得不握着棍子说话”组中的棍子一样。你的第一个例子是,一个人问某人一个问题,然后拒绝放弃棍子,直到问题得到回答。但另一个人在拿到棍子之前无法回答!显然这里会有问题 在你的第二个例子中,这个人问了某人一个问题,在给出答案后要求别人还给他棍子,然后放弃棍子。一路上可能会有一些无关的闲聊,但至少这个问题会得到回答。好多了 (请注意,默认情况下会继续捕获上下文,因此不会更改任何内容。)