Может ли async / await по-прежнему оставаться взаимоблокировкой, если используется ConfigureAwait (false)?

#c# #async-await #deadlock

#c# #async-await #взаимоблокировка

Вопрос:

Согласно этой ссылке, с async / await может возникнуть взаимоблокировка в определенных сценариях.

Однако может ли по-прежнему возникать взаимоблокировка, если я использую ConfigureAwait(false) всегда?

Например: task.ConfigureAwait(false).GetAwaiter().GetResult()

Вместо: task.GetAwaiter().GetResult()

Комментарии:

1. Примечание: Это «настроить ожидание», а не «настроить задачу». ConfigureAwait(false) In task.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() , никогда не переключает потоки.