#c# #async-await #deadlock
#c# #async-await #взаимоблокировка
Вопрос:
Согласно этой ссылке, с async / await может возникнуть взаимоблокировка в определенных сценариях.
Однако может ли по-прежнему возникать взаимоблокировка, если я использую ConfigureAwait(false)
всегда?
Например: task.ConfigureAwait(false).GetAwaiter().GetResult()
Вместо: task.GetAwaiter().GetResult()
Комментарии:
1. Примечание: Это «настроить ожидание», а не «настроить задачу».
ConfigureAwait(false)
Intask.ConfigureAwait(false).GetAwaiter().GetResult()
не оказывает никакого влияния, потому что нетawait
необходимости настраивать.
Ответ №1:
Это все равно может привести к взаимоблокировке, если все, что должно завершиться task
, или любые другие вложенные операции захватили независимо от вашего текущего контекста, если этот контекст привязан к определенному потоку — потому что вы вызываете, GetResult
используя этот поток, и блокируете, делая его недоступным для использования другими.
Просто используйте await
. Это await
то, что может освободить ваш текущий контекст.
Ответ №2:
Да, это все еще может привести к взаимоблокировке, ConfigureAwait(false)
придется реализовать во всех вложенных ожиданиях, некоторые из которых вы можете не контролировать.
Лучший подход — не полагаться на это, просто не смешивайте синхронные и async
вызовы, позвольте Async / Await распространяться.
Единственный верный способ (и спорный) убедиться, что это не приведет к взаимоблокировке (без await
), — это разгрузить / перенести его в другую задачу и Wait
это, или быть в среде, которая не имеет SynchronizationContext
Ответ №3:
Как следует из названия, ConfigureAwait()
влияет только на асинхронность await
. Это не влияет на синхронные ожидания, такие как Task.Wait()
, Task.Result
и Task.GetAwaiter().GetResult()
.
ConfigureAwait(false)
грубо означает «Мне все равно, в каком потоке будет возобновлен код после этого async await», поэтому, если исходный поток (точнее SynchronizationContext
) чем-то заблокирован, он все равно продолжится в другом потоке. Но синхронное ожидание, подобное GetAwaiter().GetResult()
, никогда не переключает потоки.