在POST期间双击等待操作

Fal*_*ine 6 c# performance asynchronous async-await dotnet-httpclient

使用c#HttpClient来发布数据,假设我也关注返回的内容.我正在优化我的应用程序并尝试在同一方法中了解两个等待调用的性能影响.从以下代码段中弹出的问题,

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

假设我在那里有错误处理:)我知道等待电话是昂贵的所以双等待引起了我的注意.

  • 在第一次await完成后,POST响应在内存中会更有效地直接返回结果,比如 var response = post.Content.ReadAsStringAsync().Result;
  • 在同一方法中进行两次await/async调用时有哪些性能考虑因素?
  • 以上代码是否会导致每个等待线程(2个线程),或者为返回的任务处理两个await调用的1个线程?

Yuv*_*kov 8

我知道等待电话很贵,所以双重等待引起了我的注意.

你为什么说他们很贵?编译器生成的状态机是一个高度优化的野兽,它确保它不会膨胀内存.根据具体情况,例如,TaskAwaiter返回的Task是a struct而不是a class,它将不会在堆上分配.正如@usr所指出的那样,非常正确的是,通过线路发送请求会使任何状态机分配成本都可以忽略不计.

是否更有效率地直接返回结果,比如 var response = post.Content.ReadAsStringAsync().Result;

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

在同一方法中进行两次await/async调用时有哪些性能考虑因素?

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

async在大量消费者会打你的地方闪耀,你想确保你有足够的可用资源来处理这些请求.我看到人们多次问过"为什么这个异步代码没有让我的代码变得更快?".它不会做出任何明显的改变,除非你将面临繁重的流量,例如,你将强调你的IIS线程池,它将实际上从异步中受益.

以上代码是否会导致每个等待线程(2个线程),或者为返回的任务处理两个await调用的1个线程?

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