可以ConfigureAwait(假)在库失去同步上下文调用的应用程序?上下文、应用程序、ConfigureAwait

2023-09-05 00:15:59 作者:江上月卿

我从阅读的人的意见很多时候比我聪明,它有几个注意事项:始终使用 ConfigureAwait(假)库$ C $内ç。所以我相当肯定我知道答案,但我想成为100%。该方案是我有一个库,包装薄一些其他的异步库。

库code:

 公共异步任务DoThingAsyc(){
    //做一些设置
    返回等待otherLib.DoThingAsync()ConfigureAwait(假)。
}
 

应用code:

  //需要preserve我同步上下文
等待myLib.DoThingAync();
//我有我的背景在这里还是没我的lib失去它?
 

解决方案 执行上下文与调用栈

没有。

的SynchronizationContext 发生在的拍摄等待 ConfigureAwait 配置的具体等待

如果应用程序调用的库的异步方法并等待它的SC被当场擒获不管调用里面发生了什么。

现在,因为异步方法的同步部分(也就是前面的部分的第一个等待)执行任务返回之前等待,你可以摆弄在的SynchronizationContext 有,但 ConfigureAwait 并没有做到这一点。

在特定的例子中,你似乎是从异步方法返回的 ConfigureAwait 的结果。这是不可能发生的,因为 ConfigureAwait 返回 ConfiguredTaskAwaitable 结构。然而,如果我们改变了方法的返回类型:

 公共ConfiguredTaskAwaitable DoThingAsyc()
{
    返回otherLib.DoThingAsync()ConfigureAwait(假)。
}
 

然后等待它的确会影响到调用code的等待行为。

I've read the advice many times from people smarter than me, and it has few caveats: Always use ConfigureAwait(false) inside library code. So I'm fairly certain I know the the answer, but I want to be 100%. The scenario is I have a library that thinly wraps some other asynchronous library.

Library code:

public async Task DoThingAsyc() {
    // do some setup
    return await otherLib.DoThingAsync().ConfigureAwait(false);
}

Application code:

// need to preserve my synchronization context
await myLib.DoThingAync();
// do I have my context here or did my lib lose it?

解决方案

No.

The capturing of the SynchronizationContext happens on await. ConfigureAwait configures the specific await.

If the application calls a library's async method and awaits it the SC is captured on the spot regardless of what happens inside the call.

Now, because the async method's synchronous part (which is the part before the first await) is executed before a task is returned to be awaited, you can mess around with the SynchronizationContext there, but ConfigureAwait doesn't do that.

In your specific example you seem to be returning the result of ConfigureAwait from the async method. That can't happen because ConfigureAwait returns the ConfiguredTaskAwaitable struct. If however we change the method return type:

public ConfiguredTaskAwaitable DoThingAsyc() 
{
    return otherLib.DoThingAsync().ConfigureAwait(false);
}

Then awaiting it will indeed affect the calling code's await behavior.

 
精彩推荐