Я столкнулся с некоторыми передовыми практиками асинхронного программирования с использованием ключевых слов async
/ await
слов в C # (я новичок в C # 5.0).
Один из полученных советов был следующим:
Стабильность: знайте свои контексты синхронизации
... Некоторые контексты синхронизации не реентерабельные и однопоточные. Это означает, что только одна единица работы может быть выполнена в контексте в данный момент времени. Примером этого является поток пользовательского интерфейса Windows или контекст запроса ASP.NET. В этих контекстах однопоточной синхронизации легко зайти в тупик. Если вы запускаете задачу из однопоточного контекста, а затем ожидаете ее выполнения в контексте, ваш код ожидания может блокировать фоновую задачу.
public ActionResult ActionAsync()
{
// DEADLOCK: this blocks on the async task
var data = GetDataAsync().Result;
return View(data);
}
private async Task<string> GetDataAsync()
{
// a very simple async method
var result = await MyWebService.GetDataAsync();
return result.ToString();
}
Если я попытаюсь проанализировать его сам, основной поток порождает новый MyWebService.GetDataAsync();
, но, поскольку основной поток ждет там, он ожидает результата в GetDataAsync().Result
. Между тем говорят, что данные готовы. Почему основной поток не продолжает свою логику продолжения и не возвращает строковый результат GetDataAsync()
?
Может кто-нибудь объяснить мне, почему в приведенном выше примере тупик? Я совершенно не понимаю, в чем проблема ...