Использование асинхронного действия для запуска синхронного кода - PullRequest
14 голосов
/ 09 марта 2012

У меня есть действие поиска, которое имеет два пути: синхронный путь, который просто возвращает простое представление, и асинхронный путь, который выполняет поиск асинхронно, а затем возвращает представление.Оба являются запросами GET, поэтому они являются частью одного и того же действия.

Проблема в том, что когда я получаю доступ к действию "localhost: XXXX / Home / Search", страница просто бесконечно загружается.Используя Fiddler, я вижу, что запрос никогда не возвращается.Я отладил его, и он дошел до последней строки кода, но, опять же, запрос не завершен.

Я упростил воспроизведение до следующего:

public async Task<ActionResult> Search() 
{ 
    return View(); 
} 

VS11 предупреждает меня, что код будет выполняться синхронно без ожидания, что нормально, но запрос не выполняется.

Должно ли это работать?Или мне нужно сделать что-то еще здесь?

Редактировать

Это MVC 4 для .NET 4.5.

Редактировать 2

Для тех, кто видит вещи лучше в коде, вот почему мне нужно синхронное действие в асинхронном действии:

public async Task<ActionResult> Search(string query = null)
{
    if (string.IsNullOrWhiteSpace(query))
        return View(new SearchViewModel());   // never loads

    var model = await _someService.SearchAsync(query);
    return View(model);    // loads
}

1 Ответ

17 голосов
/ 09 марта 2012

Это известная ошибка в бета-версии. Цитата Стивена Туба:

Краткий ответ: в ASP.NET MVC есть бета-версия .NET 4.5 Beta, которая приводит к этой проблеме, когда асинхронный метод выполняется синхронно. Пока исправление не доступно, простой обходной путь - добавить "await Task.Yield ();" в качестве первой строки асинхронного метода, заставляя его завершаться асинхронно. Чтобы это работало правильно, вам также необходимо убедиться, что вы используете новый SynchronizationContext, предоставляемый ASP.NET в .NET 4.5, что означает наличие строки:

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />

в разделе appSettings вашего файла конфигурации.

...