Async и ждут в контроллере MVC 4
Каждый раз, когда я пытаюсь использовать новые операторы Async
и Await
и возвращать коллекцию объектов из базы данных, я получаю исключение Invalid Operation
. Когда я использую его, чтобы возвращать только один элемент, он отлично работает.
Код контроллера:
public async Task<ActionResult> EnvironmentList()
{
EfEnvironmentDataAccess dataAccess = new EfEnvironmentDataAccess();
ICollection<Environment> environments = await dataAccess.GetAllEnvironmentsAsync();
return PartialView(environments);
}
Просмотр кода:
<div class="ECURightCol">
<h3>Table Dumps</h3>
@Html.Action("EnvironmentList", "Environment")
@Html.Action("ComputerList", "Computer")
@Html.Action("ProductList", "Product")
@Html.Action("InstanceList", "Instance")
@Html.Action("ProfileList", "Profile")
Код доступа к данным:
public ICollection<Environment> GetAllEnvironments()
{
using (EcuWebDataContext db = new EcuWebDataContext())
{
return db.Environments.OrderBy(e => e.Name).ToList();
}
}
public async Task<ICollection<Environment>> GetAllEnvironmentsAsync()
{
return await Task.Run(() => GetAllEnvironments());
}
Ошибка, которую я получаю:
Описание: Необработанное исключение возникло во время выполнения текущего веб-запроса. Просмотрите трассировку стека для получения дополнительной информации об ошибке и ее возникновении в коде.
Сведения об исключении: System.InvalidOperationException: HttpServerUtility.Execute заблокировано, ожидая завершения асинхронной операции.
Ответы
Ответ 1
Прежде всего, вы не можете использовать асинхронную обработку с дочерними действиями, и я полагаю, это то, что вы пытаетесь сделать.
Во-вторых, вы не выполняете асинхронную обработку здесь, откручивая другой поток, чтобы выполнить код с помощью следующей строки кода:
Task.Run(() => GetAllEnvironments());
Он будет блокировать поток в конце дня, и у вас не будет ничего, кроме служебных ресурсов коммутатора контекста. EF6 будет поддерживать асинхронную обработку. Для асинхронных запросов с чистым ADO.NET посмотрите:
Асинхронные вызовы базы данных с помощью модели асинхронного программирования на основе задач (TAP) в ASP.NET MVC 4
Ответ 2
Прошло много времени с тех пор, как на этот вопрос был дан ответ, но другой путь заключается в следующем:
Вызовите свой метод из действия
@Html.Action("YourSyncMethod", "YourController")
Определите его как обычное синхронизирующее действие
public ActionResult YourSyncMethod()
Затем внутри него вызовите свой асинхронный метод
var taskResponse = YourAsyncMethod();
который вернет модель с тем, что вам нужно
private async Task<YourModel> YourAsyncMethod()
Это кажется проще, чем изменять параметры конфигурации или создавать более сложный код
Ответ 3
Прошло некоторое время с момента ответа на этот вопрос. Но у меня была аналогичная ситуация с MVC 5, и я смог сделать работу [ChildActionOnly] асинхронно, просто комментируя следующую строку в разделе <system.web>
файла web.config.
<system.web>
<!--<httpRuntime targetFramework="4.5" />-->
EDIT:
Подумайте об этом, пока вы найдете реальное решение для своей ситуации. Пожалуйста, ознакомьтесь с комментариями Leri ниже.