C# 投递过程中的双重等待操作

C# 投递过程中的双重等待操作,c#,performance,asynchronous,async-await,dotnet-httpclient,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.

使用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;
    }
}
公共静态异步任务AsyncRequest(字符串URL,字符串数据=null)
{
使用(var client=new HttpClient())
{
var post=await client.PostAsync(URL,新的StringContent(数据,Encoding.UTF8,“application/json”)).ConfigureAwait(false);
post.EnsureSuccessStatusCode();
var response=wait post.Content.ReadAsStringAsync();
返回响应;
}
}
假设我在那里有错误处理:) 我知道等待电话很贵,所以双重等待引起了我的注意

  • 在第一次等待完成后,POST响应在内存中,直接返回结果是否更有效,如
    var response=POST.Content.ReadAsStringAsync().result
  • 在同一方法中进行两个wait/async调用时,性能注意事项是什么
  • 上面的代码会为每个等待生成一个线程(2个线程),还是为处理两个等待调用的返回任务生成一个线程
我知道等待电话很贵,所以双重等待吸引了我的注意力 注意

你为什么说它们很贵?编译器生成的状态机是一个高度优化的beast,确保它不会占用内存。具体来说,例如,从
Task
返回的
TaskAwaiter
struct
而不是
类,因此不会在堆上分配它。正如@usr指出的,并且非常正确的是,通过线路发送请求将使任何状态机分配成本都可以忽略

直接返回结果会更有效吗,比如
var响应
=post.Content.ReadAsStringAsync().Result

将您的方法标记为async
就足够让编译器生成一个状态机了。堆栈变量将被提升到创建的状态机。一旦你的第一个
wait
被点击,剩下的代码就会变成一个继续。使用
post.Content.ReadAsStringAsync().Result
更可能导致代码死锁,而不是节省内存消耗或使代码快一毫秒

在进行两个wait/async时,性能注意事项是什么 用相同的方法调用

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

async
在有大量消费者会打你的地方大放异彩,你需要确保你有足够的可用资源来处理这些请求。我看到人们多次问“为什么异步代码不能让我的代码运行得更快?”。它不会做出任何明显的改变,除非您将处于高流量下,流量足够大,例如,您将对IIS线程池施加压力,因为它实际上将从异步中获益

上述代码会导致每等待一个线程(2个线程)还是1个线程 将处理两个等待调用的返回任务的线程


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

1。没关系。没有,它使用线程池,如果您的方法正在等待,PostAsync可以接受AsyncRequest线程,因此没有区别3。线程池:)一个线程更改操作,但是-实际上-这取决于JIT编译器。与HTTP请求相比,等待轮数的成本为零。一位同事提到这是一个昂贵的调用,但我是TPL新手,因此我可能不知道该评论的上下文。你提出了一个关于并发性的好问题,这是我研究的核心。我正在测试一个web api的性能-比较同步/异步调用和单次/批量调用。谢谢你的好消息!