POST期间双重等待操作

Double await operations during POST

使用 c# HttpClient 处理 POST 数据,假设我也关心 returned 内容。我正在优化我的应用程序并尝试了解同一方法中两次等待调用对性能的影响。从以下代码片段中弹出问题,

public static async Task<string> AsyncRequest(string URL, string data = null)
{
    using (var client = new HttpClient())
    {
        var post = await client.PostAsync(URL, new StringContent(data, Encoding.UTF8, "application/json")).ConfigureAwait(false);
        post.EnsureSuccessStatusCode();

        var response = await post.Content.ReadAsStringAsync();
        return response;
    }
}

假设我在那里有错误处理:) 我知道等待调用很昂贵,所以双重等待引起了我的注意。

I know await calls are expensive so the double await caught my attention.

为什么说贵?编译器生成的状态机是一个高度优化的野兽,确保它不会膨胀内存。具体来说,例如,从 Task 返回的 TaskAwaiterstruct 而不是 class,因此它不会在堆上分配。正如@usr 指出的那样,并且非常正确,通过网络发送请求将使任何状态机分配成本都可以忽略不计。

would it be more efficient to return the result directly, like var response = post.Content.ReadAsStringAsync().Result;

标记您的方法 async 足以让编译器生成状态机。堆栈变量已经被提升到创建的状态机。一旦你的第一个 await 被命中,你的代码的其余部分无论如何都会变成一个延续。使用 post.Content.ReadAsStringAsync().Result; 更有可能导致 死锁 您的代码,而不是为您节省任何内存消耗或使您的代码更快微毫秒。

What are the performance considerations when making two await/async calls in the same method?

从性能的角度来看,您应该问自己的问题是 - 并发性是否会成为我的应用程序中的一个问题,从而值得使用异步操作?

async 在大量消费者会打你的地方闪耀,你想确保你有足够的可用资源来处理这些请求。我看到人们问了很多次"why isn't this async code making my code go faster?"。它 不会 做出任何显着的改变,除非你将在繁忙的交通中,例如,你会强调你的 IIS 线程池,它实际上会受益来自异步。

Will the above code result in a thread per await (2 threads), or 1 thread for the returned Task that will handle both await calls?

取决于您的环境。当您的第一个 await 被命中时,您明确告诉它不要用 ConfigureAwait(false) 编组任何同步上下文。例如,如果您是来自 UI 线程的 运行,那么 PostAsync 之后的任何代码都将是线程池工作线程上的 运行。同样,这对您来说不应该是一个问题,这些是微优化,您不会从中看到任何好处。