C#异步/等待链与ConfigureAwait(false) [英] C# async/await chaining with ConfigureAwait(false)
问题描述
基于众多书籍和博客,其中包括这里的优秀书籍 ,很明显,当编写一个DLL库公开辅助异步方法(即包装器方法)时,通常认为是在内部像这样在线程池线程上完成实际异步方法的I / O任务的最佳实践(如下所示的伪代码)为了简洁起见,我以 HttpClient
为例)
Based on numerous books and blogs including this excellent one here, it is clear that when one writes a dll library exposing helper async methods i.e. the wrapper methods, it is generally considered a best practice to internally complete the I/O task of actual async methods on a threadpool thread like so (pseudo code shown below for brevity and I'm using HttpClient
as an example)
public Async Task<HttpResponseMessage> MyMethodAsync(..)
{
...
var httpClient = new HttpClient(..);
var response = await httpClient.PostAsJsonAsync(..).ConfigureAwait(false);
...
return response;
}
此处的关键是 ConfigureAwait(false )
,以便IO任务完成发生在线程池线程上,而不是在原始线程上下文上,从而有可能防止死锁。
The key here is the usage of ConfigureAwait(false)
so that IO task completion occurs on a threadpool thread instead of on the original thread context, thereby potentially preventing deadlocks.
我的问题是呼叫者的观点。我对在调用方和上面的方法调用之间存在方法调用层的情况特别感兴趣,如以下示例所示。
My question is from the perspective of a caller. I'm particularly interested in a scenario where there are layers of method calls between the caller and the above method call, as the following example shows.
CallerA -> Method1Async -> Method2Async -> finally the above MyMethodAsync
是否足以拥有 ConfigureAwait(false)
仅用于最后一种方法,或者还应确保 Method1Async
和 Method2Async
也在内部调用其异步方法 ConfigureAwait(false)
与?
将其包含在所有这些中间方法中似乎很可笑,尤其是如果 Method1Async
和 Method2Async
重载最终调用 MyMethodAsync
。
有什么想法,请启发我们!
Is it enough to have ConfigureAwait(false)
on the final method only or should one also ensure Method1Async
and Method2Async
also internally call their async methods with ConfigureAwait(false)
?
It seems silly to have it included on all these intermediary methods, especially if Method1Async
and Method2Async
are simply overloads that end up calling MyMethodAsync
.
Any thoughts, please enlighten us!
已通过示例更新
所以,如果我有一个图书馆,其中有以下私人图书馆异步方法
Updated with Example So if I have a library with the following private async method,
private async Task<string> MyPrivateMethodAsync(MyClass myClass)
{
...
return await SomeObject.ReadAsStringAsync().ConfigureAwait(false);
}
我应确保以下公共重载方法也都包含ConfigureAwait(false)如下所示?
should I make sure the following public overloaded methods both also include ConfigureAwait(false) as shown below?
public async Task<string> MyMethodAsync(string from)
{
return await MyPrivateMethodAsync(new (MyClass() { From = from, To = "someDefaultValue"}).ConfigureAwait(false);
}
public async Task<string> MyMethodAsync(string from, string to)
{
return await MyPrivateMethodAsync(new (MyClass() { From = from, To = to }).ConfigureAwait(false);
}
推荐答案
绝对不是。 ConfigureAwait
就像其名称一样建议配置 await
,仅影响 await
Definitely not. ConfigureAwait
just as it's name suggest configures the await
. It only affects the await
coupled with it.
ConfigureAwait
实际上返回一个不同的等待类型, ConfiguredTaskAwaitable
而不是 Task
,这反过来又返回不同的等待者类型 ConfiguredTaskAwaiter
而不是 TaskAwaiter
ConfigureAwait
actually returns a different awaitable type, ConfiguredTaskAwaitable
instead of Task
which in turn returns a different awaiter type ConfiguredTaskAwaiter
instead of TaskAwaiter
如果您想为所有 SynchronizationContext
>等待,则必须使用 Co nfigureAwait(false)
。
If you want to disregard the SynchronizationContext
for all your await
s you must use ConfigureAwait(false)
for each of them.
如果要限制使用 ConfigureAwait(false)
,您可以使用我的 NoSynchronizationContextScope
(请参见此处)在最顶部:
If you want to limit the use of ConfigureAwait(false)
you can use my NoSynchronizationContextScope
(see here) at the very top:
async Task CallerA()
{
using (NoSynchronizationContextScope.Enter())
{
await Method1Async();
}
}
这篇关于C#异步/等待链与ConfigureAwait(false)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!