为什么HttpClient.PostAsync缓冲区响应?

最近我在.Net 4.5.1上使用HttpClients.PostAsync时遇到了性能问题。 最初服务器(Owin + WebApi)在发送之前缓冲响应。 这导致了巨大的内存使用开销(序列化响应大小> 1Gb)。 在我打开服务器上的响应流后,客户端字面上停止工作。 事实certificate,当从服务器读取响应时,原因是客户端上的缓冲区重新分配。 我检查了HttpClient实现,并在HttpClient.SendAsync方法中找到了这个有趣的部分:

 if (result.Content == null || completionOption == HttpCompletionOption.ResponseHeadersRead) { this.SetTaskCompleted(request, linkedCts, tcs, result); } else { this.StartContentBuffering(request, linkedCts, tcs, result); } 

因此,当completionOptionResponseHeadersRead时, ResponseHeadersRead响应总是被缓冲。 根据SendAsync文档 ,SendAsync的实现与意图一致。

现在,当PostAsync实现发送ResponseContentRead ,响应流总是在POST上缓冲。 所以问题是为什么PostAsync必须等待(和缓冲)整个响应才能在处理继续之前到达?

有明显的部分 – 如果你没有指定HttpCompletionOption.ResponseHeadersReadTask只会在读取整个响应时完成; 你必须在此期间将响应数据存储在某个地方

为什么PostAsync不允许您指定HttpCompletionOption.ResponseHeadersRead ? 可能是因为大多数时候它并不是那么有用。 POST用于发布数据,而不是用于检索数据 – 这是GET的工作。 HttpClient是围绕WebAPI和“REST”服务设计的,正确使用了HTTP动词。

如果需要使用POST来检索如此大量的数据,则有两个基本选项:

  • 使用SendAsync
  • 不要使用HttpClientHttpWebRequest有点复杂,但是给你更多的控制权)