Асинхронная ошибка CTP - задача никогда не завершается

Во-первых, прошу прощения: я не могу выделить следующую ошибку в простое консольное приложение. Однако в моем относительно простом приложении ASP.NET Web Forms следующий код приведет к тому, что текущий поток будет блокироваться бесконечно:

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". Кто-нибудь знает, почему это произойдет?

1 ответ

Решение

РЕДАКТИРОВАТЬ: комментарий от Стивена Клири проливает больше света:

AspNetSynchronizationContext самая странная реализация. Он рассматривает Post как синхронный, а не асинхронный и использует блокировку для выполнения своих делегатов по одному. AspNetSynchronizationContext не требует маршалинга обратно в один и тот же поток (но требует снятия блокировки); тупик на Wait потому что продолжение ожидает блокировки (удерживается потоком в обработчике событий)


Я думаю, что есть SynchronizationContext что заставляет продолжение работать в том же потоке, что и обработчик событий. Ваш обработчик событий блокирует этот поток, поэтому продолжение никогда не запускается, что означает, что обработчик событий никогда не разблокируется.

Хотя это только предположение - это единственная вещь, о которой я могу думать, которая имеет смысл в данный момент.

Один из вариантов, чтобы попытаться разблокировать это, чтобы изменить Sleep метод для:

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

Это позволит продолжить продолжение в другом контексте.

Я удивлен, что есть такой контекст синхронизации, заметьте... Я ожидаю, что все это произойдет в пуле потоков. возможно BeginRequest лечится слегка специально.

Другие вопросы по тегам