POST 期间的双重等待操作
Posted
技术标签:
【中文标题】POST 期间的双重等待操作【英文标题】:Double await operations during POST 【发布时间】:2015-06-29 17:31:09 【问题描述】:使用 c# HttpClient 发布数据,假设我也关心返回的内容。我正在优化我的应用程序并试图了解在同一方法中两次等待调用的性能影响。从下面的代码sn-p中跳出来的问题,
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;
假设我在那里有错误处理:) 我知道 await 调用很昂贵,所以双重 await 引起了我的注意。
第一次等待完成后,POST 响应在内存中,直接返回结果会不会更高效,例如var response = post.Content.ReadAsStringAsync().Result;
在同一方法中进行两次 await/async 调用时有哪些性能注意事项?
上面的代码会导致每个 await 线程(2 个线程),还是返回 Task 的 1 个线程来处理两个 await 调用?
【问题讨论】:
1.没关系 2. 没有,它使用线程池,如果您的方法正在等待,则 PostAsync 可以采用 AsyncRequest 线程,所以没有区别 3. 线程池 :) 一个线程更改操作,但是 - 真的 - 它取决于JIT 编译器 与 HTTP 请求相比,await 的开销为零。 【参考方案1】:我知道 await 调用很昂贵,所以双重 await 抓住了我 注意。
为什么说它们很贵?编译器生成的状态机是一种高度优化的野兽,可确保它不会膨胀内存。具体来说,例如,从Task
返回的TaskAwaiter
是struct
而不是class
,因此它不会在堆上分配。正如@usr 指出的那样,并且非常正确,通过网络发送请求将使任何状态机分配成本都可以忽略不计。
直接返回结果会不会更高效,比如
var response = post.Content.ReadAsStringAsync().Result;
标记您的方法async
足以让编译器生成状态机。堆栈变量将已经被提升到创建的状态机。一旦你的第一个await
被击中,你的其余代码无论如何都会变成一个延续。使用post.Content.ReadAsStringAsync().Result;
更有可能导致您的代码死锁,而不是为您节省任何内存消耗或使您的代码速度加快微毫秒。
进行两次等待/异步时的性能注意事项是什么 调用相同的方法?
从性能的角度来看,您应该问自己的是——并发性是否会成为我的应用程序中的一个问题,从而值得使用异步操作?
async
在大量消费者会打击你的地方大放异彩,并且你希望确保有足够的可用资源来处理这些请求。我看到人们多次问“为什么这个异步代码不能让我的代码运行得更快?”。它不会产生任何明显的变化,除非您将处于繁忙的流量之下,例如,您将强调您的 IIS 线程池,它实际上将从异步中受益。
上面的代码会导致每个等待线程(2个线程),还是1个 处理两个等待调用的返回任务的线程?
取决于您的环境。当你的第一个await
被命中时,你明确告诉它不要用ConfigureAwait(false)
编组任何同步上下文。例如,如果您从 UI 线程运行它,那么PostAsync
之后的任何代码都将在线程池工作线程上运行。同样,这不应该是您关心的问题,这些是您不会看到任何好处的微优化。
【讨论】:
一位同事提到这是一个昂贵的电话,但我是 TPL 的新手,所以我可能已经忘记了评论的上下文。你提出了一个关于并发的好问题,这就是我研究的核心。我正在测试 web api 的性能 - 比较同步/异步调用和单/批量调用。感谢您提供的重要信息!以上是关于POST 期间的双重等待操作的主要内容,如果未能解决你的问题,请参考以下文章
IE11 在来自 iFrame 的 Ajax POST 操作期间返回状态 0(XMLHttpRequest:网络错误 0x2ee2