當在異步函數中使用不同的SynchronizationContext而不是外部時,我遇到了令人困惑的行爲。等待不使用當前的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);
}
}
我得到的行爲是每個await後面的代碼都是在一個看似隨機的線程中執行的。有時候,WeShouldBeInTheMainThreadNow()運行在線程池線程中,有時運行在主線程中。有時WeShouldBeInAThreadPoolThread()正在運行
我沒有在這裏看到一個模式,但我認爲無論什麼SynchronizationContext.Current被設置在你使用await的那一行是將定義在await後面的代碼的位置執行。這是一個不正確的假設嗎?如果是這樣,有沒有一種緊湊的方式來做我想在這裏做的事情?
有沒有保證,如果任務(或其他awaitable)實際上已經被你執行'await'的時間內完成將發生的任何線程切換 - 永遠記住,代碼可以止矣跑過這一點。 – 2014-10-07 14:29:50