ConfigureAwait:处理异常的线程在哪?

Pet*_*erg 6 .net c# async-await

当你awaita时Task,默认的延续在同一个线程上运行.您实际需要的唯一时间是,如果您在UI线程上,并且延续也需要在UI线程上运行.

你可以通过使用ConfigureAwait,例如:

await SomeMethodAsync().ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)

...这对于从不需要在那里运行的UI线程卸载工作非常有用.(但请参阅Stephen Cleary在下面的评论.)

现在考虑这段代码:

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

那怎么样?

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?
}
Run Code Online (Sandbox Code Playgroud)

Sco*_*ain 8

如果没有异常,那么异常将在继续发生的任何线程上.

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.
}
Run Code Online (Sandbox Code Playgroud)

为了更清晰:

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.
}
Run Code Online (Sandbox Code Playgroud)