Do not expect to use the current SynchronizationContext

I get confusing behavior when using a different SynchronizationContext inside an asynchronous function than outside.

Most of my program codes use a custom SynchronizationContext, which simply queues SendOrPostCallbacks and calls them at a certain known point in my main thread. I set this custom SynchronizationContext at the beginning of time, and everything works fine when I use only this one.

The problem I'm facing is that I have functions that I want their expectations to continue to run in the thread pool.

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 , await, , , , . ? , , ?

+4
2

await, - async -.

await , , .

await Blah(); var blahTask = Blah(); await blahTask;

, , await ?

// Synchronization Context leads to main thread;
Task<int> xTask = SomeOtherFunction();
// Synchronization Context has already been set 
// to null by SomeOtherFunction!
int x = await xTask;

: finally , , - SynchronizationContext, SynchronizationContext () , . , , SynchronizationContext, , SynchronizationContext , (, SynchronizationContext.Current ...)

, , , . ( - ...)

, await .

, " , await , await", ConfigureAwait(false) ;

async Task SomeOtherFunction() {
    await Blah().ConfigureAwait(false);
}

, " , await " - - , , await, , ContinueWith - Task, .

Task SomeOtherFunction() {
    return Blah()
        .ContinueWith(blahTask => WeShouldBeInAThreadPoolThread(),
                      TaskScheduler.Default);
}
+1

, , , :

  • , SynchronizationContext , .
  • SynchronizationContext.
  • SynchronizationContext - , (, ) , .
  • SynchronizationContext ConfigureAwait(false) .
+2

All Articles