异步CTP错误 - 任务永远不会完成

Law*_*eld 4 .net c# asp.net task-parallel-library async-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));
    }
}
Run Code Online (Sandbox Code Playgroud)

任务状态仍然是'WaitingForActivation'.有谁知道为什么会这样?

Jon*_*eet 5

编辑:Stephen Cleary的评论更加清晰:

AspNetSynchronizationContext是最奇怪的实现.它将Post视为同步而非异步,使用锁定一次执行一个委托.AspNetSynchronizationContext不需要编组回到同一个线程(但需要锁定); 死锁Wait是因为continuation正在等待锁定(由事件处理程序中的线程持有)


我的猜测是,有一个SynchronizationContext强制继续在与事件处理程序相同的线程上运行.您的事件处理程序阻止该线程,因此延续从不运行,这意味着事件处理程序永远不会解除阻塞.

这只是猜测 - 这是我能想到的唯一有意义的东西.

尝试取消阻止此操作的一个选项是将您的Sleep方法更改为:

private async Task Sleep()
{
    await TaskEx.Run(() => System.Threading.Thread.Sleep(1000))
                .ConfigureAwait(continueOnCapturedContext: false);
}
Run Code Online (Sandbox Code Playgroud)

这将允许继续在不同的上下文中完成.

我很惊讶有这样的同步情况下,你要知道......我希望这一切只是发生在线程池.可能BeginRequest会稍微特别对待.