Я знаю, что в случае существующего SynchronizationContext исходный поток будет использоваться снова после ожидания, если ConfigureAwait (false) не вызывается.Это не тема этого вопроса.
Ну, нет и да.
Нет, SynchronizationContext
делает не обязательно означает "та же самая тема",Это просто означает «тот же контекст».Если этот контекст является контекстом пользовательского интерфейса, то этот контекст ссылается на тот же поток (поток пользовательского интерфейса).Если этот контекст является контекстом пула потоков, то этот контекст может ссылаться на любой поток пула потоков.
И да, это действительно тема этого вопроса, потому что текущий SynchronizationContext
(или текущий TaskScheduler
, если нет текущего SynchronizationContext
) определяет, в каком потоке возобновляется метод.
В каких особых случаях асинхронный поток продолжается в другом потоке?
В тот момент, когда await
нужно асинхронно выдавать, захватит его контекст (SynchronizationContext
или TaskScheduler
).Когда метод готов к возобновлению, он возобновляется в этом контексте.Обычно это либо контекст пользовательского интерфейса (который привязан к определенному потоку пользовательского интерфейса), либо контекст пула потоков (который может использовать любой поток пула потоков).
ConfigureAwait(continueOnCapturedContext: false)
переопределяет это поведение и всегда планирует продолжения напоток пула потоков.
Обратите внимание, что в случае пула потоков метод async
может возобновиться или не возобновиться в том же потоке, в котором он запущен.Это не обязательно означает другой поток пула потоков - это может быть любой поток пула потоков вообще.
Возможно ли принудительно заставить все асинхронные методы в дереве вызововвытеснены в той же теме?(Мне это не нужно, но я просто хочу понять, почему это невозможно ...)
Вы не можете заставить это, но выможет сделать это поведением по умолчанию.Вы можете создать однопоточный SynchronizationContext
(или TaskScheduler
) и выполнить в нем асинхронный код.Если вы сделаете это, то по умолчанию await
возобновится в том же потоке;но если он хочет, то асинхронный код может обойти этот контекст, просто используя ConfigureAwait(false)
, а затем возобновить работу в потоке пула потоков.
AsyncContext
является примеромоднопоточный SynchronizationContext
.