【发布时间】:2015-04-30 20:01:29
【问题描述】:
根据包括this excellent one here在内的大量书籍和博客,很明显,当一个dll库公开辅助异步方法(即包装方法)时,通常认为在内部完成实际的I/O任务是一种最佳实践。像这样的线程池线程上的异步方法(为简洁起见,下面显示了伪代码,我以HttpClient 为例)
public Async Task<HttpResponseMessage> MyMethodAsync(..)
{
...
var httpClient = new HttpClient(..);
var response = await httpClient.PostAsJsonAsync(..).ConfigureAwait(false);
...
return response;
}
这里的关键是ConfigureAwait(false) 的使用,这样IO 任务完成发生在线程池线程上,而不是在原始线程上下文上,从而潜在地防止死锁。
我的问题是从来电者的角度出发的。我对调用者和上述方法调用之间存在多层方法调用的场景特别感兴趣,如下例所示。
CallerA -> Method1Async -> Method2Async -> finally the above MyMethodAsync
仅在最终方法上使用ConfigureAwait(false) 是否足够,或者是否还应该确保Method1Async 和Method2Async 也在内部使用ConfigureAwait(false) 调用它们的异步方法?
将它包含在所有这些中间方法中似乎很愚蠢,特别是如果Method1Async 和Method2Async 只是最终调用MyMethodAsync 的重载。
有什么想法,请赐教!
使用示例更新 因此,如果我有一个具有以下私有异步方法的库,
private async Task<string> MyPrivateMethodAsync(MyClass myClass)
{
...
return await SomeObject.ReadAsStringAsync().ConfigureAwait(false);
}
我是否应该确保以下公共重载方法都包括 ConfigureAwait(false),如下所示?
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(false)是库代码的好习惯,但它的使用可能有其自身的含义:stackoverflow.com/q/28410046
标签: c# .net task-parallel-library async-await io-completion-ports