异步CTP错误 – 任务永远不会完成
首先是道歉:我无法将以下错误隔离到一个简单的控制台应用程序中。 但是,在我相对简单的ASP.NET Web窗体应用程序中,以下代码将导致当前线程无限期地阻塞:
public class MyModule : IHttpModule { public void Dispose() { } public void Init(System.Web.HttpApplication context) { context.BeginRequest += this.Context_BeginRequest; } private void Context_BeginRequest(object sender, EventArgs e) { Sleep().Wait(); var x = 2; // This line is never hit. } private async Task Sleep() { await TaskEx.Run(() => System.Threading.Thread.Sleep(1000)); } }
任务状态仍然是’WaitingForActivation’。 有谁知道为什么会这样?
编辑:Stephen Cleary的评论更加清晰:
AspNetSynchronizationContext
是最奇怪的实现。 它将Post视为同步而非异步,并使用锁定一次执行一个委托 。AspNetSynchronizationContext
不需要编组回同一个线程(但需要锁定);Wait
上的死锁是因为continuation正在等待锁定(由事件处理程序中的线程持有)
我的猜测是有一个SynchronizationContext
,它强制继续在与事件处理程序相同的线程上运行。 您的事件处理程序阻止该线程,因此延续永远不会运行,这意味着事件处理程序永远不会解除阻塞 。
这只是猜测 – 这是我能想到的唯一有意义的东西。
尝试取消阻止此操作的一个选项是将Sleep
方法更改为:
private async Task Sleep() { await TaskEx.Run(() => System.Threading.Thread.Sleep(1000)) .ConfigureAwait(continueOnCapturedContext: false); }
这将允许继续在不同的上下文中完成。
我很惊讶有这样的同步上下文,请注意……我希望所有这些都发生在线程池上。 可能会稍微特别对待BeginRequest
。