Я пытаюсь понять, почему метод async void в приложении ASP.Net может привести к следующему исключению, в то время как кажется, что async Task не будет:
System.InvalidOperationException: An asynchronous module or handler
completed while an asynchronous operation was still pending
Я относительно новичок в мире async в .NET, но чувствую, что я попытался запустить его с помощью нескольких существующих ресурсов, включая все следующие:
- Какая разница между возвратом void и возвратом задачи?
- Все о SynchronizationContext
- Асинхронные синтаксические предложения сахара
- Async в ASP.NET
Из этих ресурсов я понимаю, что наилучшей практикой является, как правило, возврат задачи и исключение async void. Я также понимаю, что async void увеличивает количество выдающихся операций при вызове метода и уменьшает его при завершении. Это звучит, по крайней мере, как часть ответа на мой вопрос. Однако то, что мне не хватает, это то, что происходит, когда я возвращаю Task и почему это делает вещи "работающими".
Вот надуманный пример, который еще раз иллюстрирует мой вопрос:
public class HomeController : AsyncController
{
// This method will work fine
public async Task<ActionResult> ThisPageWillLoad()
{
// Do not await the task since it is meant to be fire and forget
var task = this.FireAndForgetTask();
return await Task.FromResult(this.View("Index"));
}
private async Task FireAndForgetTask()
{
var task = Task.Delay(TimeSpan.FromSeconds(3));
await task;
}
// This method will throw the following exception:
// System.InvalidOperationException: An asynchronous module or
// handler completed while an asynchronous operation was still pending
public async Task<ActionResult> ThisPageWillNotLoad()
{
// Obviously can't await a void method
this.FireAndForgetVoid();
return await Task.FromResult(this.View("Index"));
}
private async void FireAndForgetVoid()
{
var task = Task.Delay(TimeSpan.FromSeconds(3));
await task;
}
}
В отношении связанного примечания, если мое понимание асинхронного права правильное, тогда не так ли неправильно думать о async void как о "пожаре и забыть" в этом сценарии, поскольку ASP.Net на самом деле не забывает об этом?