配置等待:在哪个线程上处理异常

本文关键字:线程 处理 异常 等待 配置 | 更新日期: 2023-09-27 18:32:50

当你await一个Task时,默认情况下,延续在同一线程上运行。您唯一实际需要它的时间是在 UI 线程上,并且延续也需要在 UI 线程上运行。

您可以使用ConfigureAwait来控制这一点,例如:

await SomeMethodAsync().ConfigureAwait(false);

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

现在考虑这段代码:

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

这又如何呢?

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?
}

配置等待:在哪个线程上处理异常

如果没有异常,异常将发生在任何线程上。

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.
}

为了更清楚一些:

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.
}