Подтвердить что ты не робот

ASP.NET MVC 4 асинхронное дочернее действие

У меня есть приложение ASP.NET MVC 4, ориентированное на .NET 4.5. Одно из наших дочерних действий вызывает вызов веб-службы с использованием HttpClient.

Поскольку мы блокируем IO, ожидая ответа HttpClient, имеет смысл преобразовать код в шаблон async/await. Однако, когда MVC 4 пытается выполнить дочернее действие, мы получаем следующее сообщение об ошибке:

HttpServerUtility.Execute заблокирован, ожидая завершения асинхронной операции.

На первый взгляд кажется, что MVC 4 не поддерживает async/wait в дочернем действии. Единственная оставшаяся опция - запустить с использованием синхронного кода и принудительно выполнить "Ожидание" в задаче async.

Как мы все знаем, касание .Result или .Wait() в async-задании в контексте ASP.NET вызовет немедленный тупик. Моя асинхронная логика завернута в библиотеку классов, поэтому я не могу использовать трюк "wait at blah.ConfigureAwait(false)". Помните, что тегирование "async" на дочернем действии и использование await вызывает ошибку, и это мешает мне настроить ожидание.

В этот момент я нарисован в углу. Есть ли способ использовать асинхронные методы в дочернем действии MVC 4? Кажется, что плоская ошибка без обходных решений.

4b9b3361

Ответ 1

Есть еще части MVC, которые не являются async -другими; Надеюсь, они будут рассмотрены в будущем. Пожалуйста, создайте для этого проблему Connect или UserVoice.

Моя асинхронная логика завернута в библиотеку классов, поэтому я не могу использовать трюк "wait at blah.ConfigureAwait(false)".

Вероятно, вы должны добавить ConfigureAwait(false) к вызовам в вашей библиотеке классов (если можете).

Вы также можете взломать альтернативное решение. Если для вашего метода библиотеки классов не нужен контекст ASP.NET, тогда у вас может быть поток потока нитей (a), ожидающий вас:

try
{
    var result = Task.Run(async () => { await MyHttpRequest(...); }).Result;
}
catch (AggregateException ex) { ... }

Эффект похож на ConfigureAwait(false): поскольку MyHttpRequest работает в контексте пула потоков, он не будет пытаться войти в контекст ASP.NET, когда он будет завершен.

Ответ 2

Формат ответа Стивена не совсем сработал у меня (возможно, это проблема асинхронного Noob, но эй).

Мне пришлось написать выражение async в этом формате, чтобы получить строго типизированное возвращаемое значение.

Person myPerson = Task.Run(() => asyncMethodWhichGetsPerson(id)).Result;