Я получаю запутанное поведение при использовании другого SynchronizationContext внутри функции async, чем снаружи.ждут не используя текущий SynchronizationContext
Большая часть кода моей программы использует настраиваемый SynchronizationContext, который просто ставит очередь SendOrPostCallbacks и вызывает их в определенной известной точке моего основного потока. Я устанавливаю этот настраиваемый SynchronizationContext в начале времени, и все работает нормально, когда я использую только этот.
Проблема, с которой я сталкиваюсь, заключается в том, что у меня есть функции, которые я хочу, чтобы их ожидания продолжались для запуска в пуле потоков.
void BeginningOfTime() {
// MyCustomContext queues each endOrPostCallback and runs them all at a known point in the main thread.
SynchronizationContext.SetSynchronizationContext(new MyCustomContext());
// ... later on in the code, wait on something, and it should continue inside
// the main thread where MyCustomContext runs everything that it has queued
int x = await SomeOtherFunction();
WeShouldBeInTheMainThreadNow(); // ********* this should run in the main thread
}
async int SomeOtherFunction() {
// Set a null SynchronizationContext because this function wants its continuations
// to run in the thread pool.
SynchronizationContext prevContext = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
try {
// I want the continuation for this to be posted to a thread pool
// thread, not MyCustomContext.
await Blah();
WeShouldBeInAThreadPoolThread(); // ********* this should run in a thread pool thread
} finally {
// Restore the previous SetSynchronizationContext.
SynchronizationContext.SetSynchronizationContext(prevContext);
}
}
Поведение, которое я получаю, состоит в том, что код сразу после каждого ожидания выполняется в кажущейся случайной цепочке. Иногда WeShouldBeInTheMainThreadNow() работает в потоке пула потоков, а иногда и в основном потоке. Иногда WeShouldBeInAThreadPoolThread() работает
Я не вижу здесь шаблона, но я думал, что независимо от того, что SynchronizationContext.Current было установлено в строке, где вы используете ожидание, это тот, который определит, где код, следующий за ожиданием, будет выполнить. Это неверное предположение? Если да, то есть ли способ сделать то, что я пытаюсь сделать здесь?
Там нет никакой гарантии, что все резьбовые выключатели будет происходить, если задача (или другой awaitable) фактически завершена к тому времени, вы выполнили 'await' - всегда помните, что код может просто продолжать пробегая мимо этой точки. –