В каких случаях асинхронные методы будут продолжены в потоке, отличном от потока, используемого до вызова await? - PullRequest
1 голос
/ 25 сентября 2019

Я узнал, что асинхронные методы не обязательно продолжаются в том же потоке, в котором они были запущены, после вызова await.

Каковы конкретные случаи, когда асинхронный поток продолжается в другом потоке?

Возможно ли принудительно заставить все асинхронные методы в дереве вызовов выполняться в одном и том же потоке?(Мне это не нужно, но я просто хочу понять, почему это невозможно ...)

Я знаю, что в случае существующего SynchronizationContext исходный поток будет использоваться снова послеподождите, если ConfigureAwait (false) не вызывается.Это не тема этого вопроса.

Заранее спасибо:)

1 Ответ

2 голосов
/ 25 сентября 2019

Я знаю, что в случае существующего SynchronizationContext исходный поток будет использоваться снова после ожидания, если ConfigureAwait (false) не вызывается.Это не тема этого вопроса.

Ну, нет и да.

Нет, SynchronizationContext делает не обязательно означает "та же самая тема",Это просто означает «тот же контекст».Если этот контекст является контекстом пользовательского интерфейса, то этот контекст ссылается на тот же поток (поток пользовательского интерфейса).Если этот контекст является контекстом пула потоков, то этот контекст может ссылаться на любой поток пула потоков.

И да, это действительно тема этого вопроса, потому что текущий SynchronizationContext(или текущий TaskScheduler, если нет текущего SynchronizationContext) определяет, в каком потоке возобновляется метод.

В каких особых случаях асинхронный поток продолжается в другом потоке?

В тот момент, когда await нужно асинхронно выдавать, захватит его контекст (SynchronizationContext или TaskScheduler).Когда метод готов к возобновлению, он возобновляется в этом контексте.Обычно это либо контекст пользовательского интерфейса (который привязан к определенному потоку пользовательского интерфейса), либо контекст пула потоков (который может использовать любой поток пула потоков).

ConfigureAwait(continueOnCapturedContext: false) переопределяет это поведение и всегда планирует продолжения напоток пула потоков.

Обратите внимание, что в случае пула потоков метод async может возобновиться или не возобновиться в том же потоке, в котором он запущен.Это не обязательно означает другой поток пула потоков - это может быть любой поток пула потоков вообще.

Возможно ли принудительно заставить все асинхронные методы в дереве вызововвытеснены в той же теме?(Мне это не нужно, но я просто хочу понять, почему это невозможно ...)

Вы не можете заставить это, но выможет сделать это поведением по умолчанию.Вы можете создать однопоточный SynchronizationContext (или TaskScheduler) и выполнить в нем асинхронный код.Если вы сделаете это, то по умолчанию await возобновится в том же потоке;но если он хочет, то асинхронный код может обойти этот контекст, просто используя ConfigureAwait(false), а затем возобновить работу в потоке пула потоков.

AsyncContext является примеромоднопоточный SynchronizationContext.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...