sar*_*ara 2 c# asp.net deadlock task async-await
编辑:我现在已经解决了这个问题,只需将按钮单击处理程序标记为async void并等待该任务.我认为除了与RegisterAsyncTask一起使用外,WebForms无法以任何方式处理异步.虽然这解决了我的问题,但我仍然对以下代码死锁的原因感兴趣,因为它违背了我目前对异步C#代码如何工作的理解,所以答案仍然受到赞赏.
我有一个服务暴露异步方法,该方法向某些api发送请求.此方法在webforms代码隐藏中使用.我知道ASP.NET只允许一次执行一个线程,因此调用Task.Wait()会导致死锁,因为等待的任务在完成后无法恢复执行,因为上下文线程被阻止.
然而,我的理解(从阅读本博客)调用ConfigureAwait(false)等待的任务导致任务在线程池线程上运行,因此可以恢复在上下文线程上的执行.我仍然从下面的代码中遇到了僵局.为什么是这样?
protected void Activate(object sender, CommandEventArgs e)
{
var someID = int.Parse((string) e.CommandArgument);
DoAsyncThingWithID(someID).Wait();
}
private async Task DoAsyncThingWithID(int ID)
{
try
{
await new SomeService()
.DoSomeAsyncWork(ID)
.ConfigureAwait(false);
}
catch (AppropriateException e)
{
DealWithIt();
}
}
Run Code Online (Sandbox Code Playgroud)
可能需要注意:DoSomeAsyncWork(int)在其下面有更多的异步方法.在底部有一个api包装对象(负责发送HTTP请求),其方法不是异步,但是调用了Task.Run(() => api.SendThingy());
这可能是问题吗?
但是,我(从阅读此博客)了解到,在等待任务上调用ConfigureAwait(false)会导致任务在线程池线程上运行,因此可以恢复上下文线程上的执行.
实际上,使用ConfigureAwait(false)意味着当前方法的延续并不关心它在哪个上下文中执行 - 而且绝大多数时候这意味着它将继续在线程池线程上运行.
因此,DoSomeAsyncWork仍将在ASP.NET上下文中运行.因此,只有一个ConfigureAwait(false)是不够的.您必须确保DoSomeAsyncWork它还使用ConfigureAwait(false)它所调用的所有异步方法,以及它们调用的所有异步方法等,包括Microsoft或第三方库方法.
这就是为什么我建议不要阻止开始.该ConfigureAwait(false)黑客只是途径之一,试图避开它,如果你绝对有来.
| 归档时间: |
|
| 查看次数: |
757 次 |
| 最近记录: |