Существует ли опасность использования ConfigureAwait (false) в контроллерах WebApi или MVC?
Скажем, у меня есть два сценария:
1) Контроллер WebApi
[System.Web.Http.HttpPost]
[System.Web.Http.AllowAnonymous]
[Route("api/registerMobile")]
public async Task<HttpResponseMessage> RegisterMobile(RegisterModel model)
{
var registerResponse = await AuthUtilities.RegisterUserAsync(model, _userService, User);
if (registerResponse.Success) {
var response = await _userService.GetAuthViewModelAsync(model.Username, User);
return Request.CreateResponse(HttpStatusCode.OK, new ApiResponseDto() { Success = true, Data = response });
}
else {
return Request.CreateResponse(HttpStatusCode.OK, registerResponse);
}
}
2) MVC-контроллер
[Route("public")]
public async Task<ActionResult> Public()
{
if (User.Identity.IsAuthenticated)
{
var model = await _userService.GetAuthViewModelAsync(User.Identity.Name);
return View("~/Views/Home/Index.cshtml", model);
}
else
{
var model = await _userService.GetAuthViewModelAsync(null);
return View("~/Views/Home/Index.cshtml", model);
}
}
Я читал, когда я должен использовать ConfigureAwait
, и мне кажется, что я должен использовать ConfigureAwait(false)
для ВСЕХ моих асинхронных вызовов, которые не привязаны непосредственно к пользовательскому интерфейсу. Я не знаю, что это значит, хотя... я должен использовать .ConfigureAwait(false)
для всех вышеперечисленных вызовов await
?
Я ищу некоторые недвусмысленные рекомендации, когда именно я должен его использовать.
Этот вопрос НЕ совпадает с Лучшей практикой для вызова ConfigureAwait для всего кода на стороне сервера - Я ищу простой ответ в прецеденте для этот метод в контексте WebApi и MVC, а не как общий С#.
Ответы
Ответ 1
похоже, что я должен использовать ConfigureAwait (false) для ВСЕХ моих асинхронных вызовов, которые не привязаны непосредственно к пользовательскому интерфейсу.
Не совсем. Это руководство не имеет смысла здесь, поскольку нет нити пользовательского интерфейса.
Параметр, передаваемый в ConfigureAwait
, равен continueOnCapturedContext
, что более четко объясняет сценарий. Вы хотите использовать ConfigureAwait(false)
всякий раз, когда остальная часть этого метода async
не зависит от текущего контекста.
В ASP.NET 4.x контекст представляет собой контекст запроса, который включает в себя такие вещи, как HttpContext.Current
и культура. Также - и это недокументированная часть - многие вспомогательные методы ASP.NET зависят от контекста запроса.
(Боковое примечание: Ядро ASP.NET больше не имеет "контекста" )
Должен ли я использовать .ConfigureAwait(false) для всех вышеперечисленных ожидающих вызовов?
Я не слышал никаких твердых рекомендаций по этому поводу, но я подозреваю, что все в порядке.
В моем собственном коде я никогда не использую ConfigureAwait(false)
в моих методах действий с контроллером, так что они уже завершаются в контексте запроса. Мне это кажется более правильным.
Ответ 2
Вы можете использовать ConfigureAwait в общедоступном действии MVC Controller, это помогает предотвратить блокировку сделки, если ваш _userService.GetAuthViewModelAsync продолжает ждать.
он тупик поднимает тупик, если служба асинхронного обслуживания продолжает ждать, поэтому может заблокировать httpcontext пользовательского интерфейса.
Посмотрите ниже ссылку, чтобы понять этот случай:
http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
Ответ 3
Async/Await - лучшие практики в асинхронном программировании
async Task MyMethodAsync()
{
// Code here runs in the original context.
await Task.Delay(1000);
// Code here runs in the original context.
await Task.Delay(1000).ConfigureAwait(
continueOnCapturedContext: false);
// Code here runs without the original
// context (in this case, on the thread pool).
}
Помимо производительности, ConfigureAwait имеет еще один важный аспект: он может избежать взаимоблокировок. Если вы добавите "ConfigureAwait (false)" в строку кода в DelayAsync, тогда тупика избегают. На этот раз, когда ожидание завершится, он попытается выполнить оставшуюся часть асинхронного метода в контексте пула потоков. Метод может завершить, что завершает возвращенную задачу, а theres нет тупика. Этот метод особенно полезен, если вам необходимо постепенно конвертировать приложение из синхронного в асинхронное.