Асинхронная ошибка CTP - задача никогда не завершается - PullRequest
4 голосов
/ 18 октября 2011

Во-первых, прямое извинение: я не могу выделить следующую ошибку в простое консольное приложение. Однако в моем относительно простом приложении 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 Ответ

5 голосов
/ 18 октября 2011

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

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


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

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

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

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

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

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

...