Async и ждут в контроллере MVC 4 - программирование
Подтвердить что ты не робот

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 заблокировано, ожидая завершения асинхронной операции.

4b9b3361

Ответ 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 ниже.