Асинхронная ошибка 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
лечится слегка специально.