HttpClient可以安全同时使用吗?


151

在所有示例中,我都能找到的用法HttpClient,它用于一次关机。但是,如果我的客户持续存在这种情况,可以同时发出多个请求怎么办?基本上,client.PostAsync针对的同一实例立即调用2个线程是否安全HttpClient

我不是在这里真正寻找实验结果。作为一个工作示例,可能只是simply幸(还有一个持久的persistent幸),而失败的示例可能是配置错误。理想情况下,我正在寻找有关HttpClient中并发处理问题的权威答案。


2
另请阅读这个问题上如何正确使用的详细信息HttpClient,并对其进行处理:stackoverflow.com/questions/15705092/...
玛尼Gandham

Answers:


152

根据MSDN,从.NET 4.5开始,以下实例方法是线程安全的(感谢@ischell):

CancelPendingRequests
DeleteAsync
GetAsync
GetByteArrayAsync
GetStreamAsync
GetStringAsync
PostAsync
PutAsync
SendAsync

3
是的,我不确定那是什么,因为它似乎是对MSDN上所有内容的标准警告(而且我还记得读过一些MSDN博客,该警告有时是错误的,因为它盲目地应用于所有内容)。
Alex K

3
这是错误的;在您链接的MSDN页面的备注部分中,它说GetAsync,PostAsync等都是线程安全的。
ischell 2013年

4
@ischell:我可以向您保证,在讨论此问题时,所讨论的段落存在。
Marcel N.

7
因此,Microsoft将HttpClient设计为可重用,但是该类具有用于标头的实例数据:client.DefaultRequestHeaders.Accept.Add(...);
cwills

8
最近,但我想评论@cwills。DefaultRequestHeaders就是默认值。如果要在每个请求基础上使用不同的标头,则可以创建新的StringContent(),在其上设置其他标头,然后使用采用URI和HttpContent的重载。
瑞安·安德森

92

这是Henrik F. Nielsen关于HttpClient的另一篇文章,他说:

默认HttpClient是开始发送请求的最简单方法。单个HttpClient可用于同时发送任意数量的HTTP请求,因此在许多情况下,您只需创建一个HttpClient,然后将其用于所有请求即可。


13
如果用户名和密码可以在线程之间更改怎么办?那就是我似乎找不到任何人在谈论的东西
Nicholas DiPiazza

1
@NicholasDiPiazza:它多久更改一次?如果存在一组已知的用户/密码对,则可以创建HttpClient实例池。
Marcel N.

是的,这就是我最终要做的
Nicholas DiPiazza

2
请注意,为所有请求重用同一HttpClient可能会导致DNS问题过时:github.com/dotnet/corefx/issues/11224
Ohad Schneider

1
@OhadSchneider如果认为该问题仅限于.net核心。您可以通过将自定义HttpClientHandler注入HttpClient构造函数,然后设置“ ConnectionLeaseTimeout”来解决.net 4问题。但是,如果100秒钟内没有请求发送到端点,则连接将自行刷新。受保护的重写Task <HttpResponseMessage> SendAsync(HttpRequestMessage request,CancellationToken cancelleToken){var sp = ServicePointManager.FindServicePoint(request.RequestUri); sp.ConnectionLeaseTimeout = 100 * 1000; }
Timothy Gonzalez

17

找到了一个MSDN论坛帖子了Henrik F. Nielsen(HttpClient的主要架构师的。

快速总结:

  • 如果您有相关的请求(或不会互相依赖),则使用相同的HttpClient很有意义。
  • 通常,我建议尽可能重用HttpClient实例。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.