简体   繁体   中英

ConfigureAwait: On which thread is the exception handled?

When you await a Task , the continuation by default runs on the same thread. The only time you ever actually need this is if you're on the UI thread, and the continuation needs to run on the UI thread as well.

You can control this by using ConfigureAwait , eg:

await SomeMethodAsync().ConfigureAwait(false);

...which can be useful to offload work from the UI thread that doesn't need to run there. (But see Stephen Cleary's comment below.)

Now consider this bit of code:

try
{
    await ThrowingMethodAsync().ConfigureAwait(false);
}
catch (Exception e)
{
    // Which thread am I on now?
}

And how about this?

try
{
    await NonThrowingMethodAsync().ConfigureAwait(false);

    // At this point we *may* be on a different thread

    await ThrowingMethodAsync().ConfigureAwait(false);
}
catch (Exception e)
{
    // Which thread am I on now?
}

The exception will be on whatever thread the continuation would have happened on had there been no exception.

try
{
    await ThrowingMethodAsync().ConfigureAwait(false);
}
catch (Exception e)
{
    // Which thread am I on now?
    //A: Likely a Thread pool thread unless ThrowingMethodAsync threw 
    //   synchronously (without a await happening first) then it would be on the same
    //   thread that the function was called on.
}

try
{
    await NonThrowingMethodAsync().ConfigureAwait(false);

    // At this point we *may* be on a different thread

    await ThrowingMethodAsync().ConfigureAwait(false);
}
catch (Exception e)
{
    // Which thread am I on now?
    //A: Likely a Thread pool thread unless ThrowingMethodAsync threw 
    //   synchronously (without a await happening first) then it would be on the same
    //   thread that the function was called on.
}

For some more clarity:

private async Task ThrowingMethodAsync()
{
    throw new Exception(); //This would cause the exception to be thrown and observed on 
                           // the calling thread even if ConfigureAwait(false) was used.
                           // on the calling method.
}

private async Task ThrowingMethodAsync2()
{
    await Task.Delay(1000);
    throw new Exception(); //This would cause the exception to be thrown on the SynchronizationContext
                           // thread (UI) but observed on the thread determined by ConfigureAwait
                           // being true or false in the calling method.
}

private async Task ThrowingMethodAsync3()
{
    await Task.Delay(1000).ConfigureAwait(false);
    throw new Exception(); //This would cause the exception to be thrown on the threadpool
                           // thread but observed on the thread determined by ConfigureAwait
                           // being true or false in the calling method.
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM