在直接从调用另一个库返回任务的库中使用ConfigureAwait(false)是否有利?
这个问题的后续行动。 我有一个包含许多异步方法的库,可以轻量地包装HttpClient
。 实际上他们只是做了一些设置并直接返回从HttpClient
调用返回的Task
:
public Task DoThingAsyc() { // do some setup return httpClient.DoThingAsync(); }
我在考虑是否将ConfigureAwait(false)
添加到这些调用中。 流行的智慧似乎是“是的,总是在图书馆那样做”。 但在这种情况下,它会引入一些(可能是可忽略的)开销,因为ConfigureAwait
返回一个ConfiguredTaskAwaitable
,需要将其包装回Task
中,以便不更改方法签名。 当然不难编码:
public async Task DoThingAsyc() { // do some setup return await httpClient.DoThingAsync().ConfigureAwait(false); }
我的问题是, ConfigureAwait(false)
的效率优势是否可能超过此案例中引入的额外开销? 以上哪个例子被认为是更好的做法?
不,不要这样做。
由于您没有使用await
,因此您不应该提前配置它。 您的库的调用者负责执行ConfigureAwait
调用。 调用者可能希望调用ConfigureAwait(true)
而不是ConfigureAwait(false)
– 你不知道。
只有在库中等待它时,才能在库代码中调用ConfigureAwait(false)
。
在大多数情况下 ,代码如下:
async Task DoSomethingAsync() { return await DoSomethingElseAsync().ConfigureAwait(false); }
相当于:
Task DoSomethingAsync() { return DoSomethingElseAsync(); }
如果 DoSomethingElseAsync
尊重Task
合同(例如,如果它返回失败的Task
而不是抛出exception)。
为此创建一个额外的状态机只是添加一层没有附加值的包装代码 – 最好直接返回Task
。
换句话说:你做这件事没有任何效率上的好处 ,恰恰相反。
不,正如其名称所示,配置await
配置。 如果您不需要await
则无需进行配置。
添加async-await只是为了使用ConfigureAwait
没有附加值,因为它只影响你的方法而不影响调用方法。 如果调用者需要使用ConfigureAwait
他们将自己这样做。
由于许多原因(例如exception处理),使用异步方法而不是简单的Task
-returning方法是有效选择,并且需要使用ConfigureAwait
但是ConfigureAwait
本身并不是一个很好的理由。