我应该在所有方法中使用配置等待,还是仅在第一个方法中使用



我有一个带有异步方法的库,我读到对于库,建议使用 ConfigureAwait(false)

例如,如果我有类似的东西:

public async Task myMethod01()
{
    await myMethod02();
}
private async Task myMethod02()
{
    await myMethod03();
}
private async Task myMethod03()
{
    await anotherMetodAsync().ConfigureAwait(false);
}

库用户只能使用method01,其他2种方法是私有的,因为它们是主要方法method01()的辅助方法。

,但我不知道是否仅在链条呼叫的第一个方法中使用ConfigureAwait,或者我应该在所有链条中使用。

tl; dr

,为了确保库中的所有异步连续性都在线程池线程上执行(取决于Synchronization -context/taskscheduler(。

您想了解更多吗?

task.configureawait(boolean(

  • true试图元使用异步方法的其余部分 回到原始上下文
  • false计划线程池线程上的异步方法的其余部分

考虑以下WPF示例:WPF使用dispatchersynchronization context在UI上下文上恢复异步连续性,因为背景线程无法更新控件的内容。

private async void Button_Click(object sender, RoutedEventArgs e)
{
    logger.LogInformation(Thread.CurrentThread.IsThreadPoolThread); //false -> GUI context
    await CompleteAsynchronously();
    logger.LogInformation(Thread.CurrentThread.IsThreadPoolThread); //false -> GUI context
    await CompleteAsynchronously().ConfigureAwait(false);
    logger.LogInformation(Thread.CurrentThread.IsThreadPoolThread); //true
}
private async Task CompleteAsynchronously()
{
    logger.LogInformation(Thread.CurrentThread.IsThreadPoolThread); //false -> GUI context
    await Task.Delay(TimeSpan.FromMilliseconds(100)).ConfigureAwait(false);
    logger.LogInformation(Thread.CurrentThread.IsThreadPoolThread); //true
}

在这里,您会发现该方法的continueOnCapturedContext标志对呼叫者没有影响。但是,当然,调用方法在呼叫者上运行的线程上运行(或至少开始运行(。

但是,仅在等待不完整的任务时才会发生当前上下文的捕获(当前SynchronizationContext;如果为null,则当前TaskScheduler(。如果任务同步完成,则continueOnCapturedContext没有效果,其余方法继续在当前线程上同步运行。

private async void Button_Click(object sender, RoutedEventArgs e)
{
    logger.LogInformation(Thread.CurrentThread.IsThreadPoolThread); //false -> GUI context
    await CompleteSynchronously().ConfigureAwait(false);
    logger.LogInformation(Thread.CurrentThread.IsThreadPoolThread); //false -> GUI context
}
private async Task CompleteSynchronously()
{
    await Task.Delay(0);
}

因此,在您的库代码(假设您不需要上下文(中,您应该始终使用ConfigureAwait(false),以确保无上下文捕获异步连续性的上下文,而不管呼叫的框架如何进入您的汇编(例如WPF,ASP.NET(核心,控制台,...(。

有关更多详细信息,请查看异步编程中的最佳实践(I.A。 ConfigureAwait(在Stephen Cleary的这篇MSDN杂志上的文章中。

您应该在所有异步调用上使用ConfigureAwait(false)。如果不执行此操作,则第一个异步调用(没有ConfigureAwait(false)(将采用同步context,当您同步在该调用上同步等待时,这可能在某些情况下(例如在ASP.NET上(造成僵局。

我的建议是阅读Stephen Cleary撰写的这篇文章。您感兴趣的部分是:

使用ConfigureAwait(false)避免死锁是危险的 实践。您将不得不使用ConfigureAwait(false) 在封闭代码调用的所有方法的及时关闭中, 包括所有第三方和第二方代码。使用 ConfigureAwait(false)避免僵局充其量只是一个黑客(。

相关内容

  • 没有找到相关文章

最新更新