C#异步/等待链与ConfigureAwait(false) [英] C# async/await chaining with ConfigureAwait(false)

查看:723
本文介绍了C#异步/等待链与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 awaits 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆