Is HttpClient safe to use concurrently?
在所有我能找到的关于HttpClient用法的例子中,它用于一次性呼叫。但是,如果我有一个持久的客户机情况,在这种情况下,可以同时发出多个请求呢?基本上,对同一个HttpClient实例同时调用2个线程上的client.PostAsync是否安全?
我不是真的在这里寻找实验结果。作为一个工作示例,可能只是一个侥幸(并且是一个持久的例子),而失败的示例可能是一个配置错误的问题。理想情况下,我正在寻找一些关于httpclient中并发处理问题的权威答案。
- 还请阅读本问题,了解如何正确使用HttpClient和处理它的更多信息:stackoverflow.com/questions/15705092/…
根据MSDN,自从.NET 4.5以下实例方法是线程安全的(谢谢@ ischell):
1 2 3 4 5 6 7 8 9
| CancelPendingRequests
DeleteAsync
GetAsync
GetByteArrayAsync
GetStreamAsync
GetStringAsync
PostAsync
PutAsync
SendAsync |
- 是的,我不确定这一点,因为它似乎是一个标准的警告,在所有的关于msdn的东西(我记得读了一些msdn博客关于什么时候该警告是错误的,因为它被盲目地应用到所有的东西)。
- @好吧,我什么都不相信。看看这个:msdn.microsoft.com/en-us/library/dd287191.aspx。所以,我一般都相信msdn。
- 好吧,博客也在msdn上,这是一个难题:)无论如何,我想我会在谨慎的立场上犯错,并根据客户的请求制定策略。
- 另一方面,HttpClient有一个cancelPendingRequests,它"取消这个实例上所有挂起的请求",这似乎意味着它可以有多个请求在运行中。
- 投反对票是怎么回事?想发表评论吗?
- 这是错误的;在您链接的msdn页面的备注部分中,它表示getasync、postsync等都是线程安全的。
- @Ischell:我可以向您保证,在讨论这个问题时,讨论的段落不在那里。
- 我看看我能做些什么来纠正这个问题。
- 仅供参考,它仍然说实例方法在msdn页面的底部不是线程安全的。
- @马特:这一直都存在,而且是关于所有.NET类型的线程安全的一般性说明。请参阅上面的msdn文章中的备注部分。
- 因此,Microsoft已经将httpclient设计为可重用的,但是该类具有头的实例数据:client.defaultRequestHeaders.accept.add(…);
- 我不确定httpclient是否是线程安全的。这里有两个场景:1。调用client.getAsync(),等待它返回一个任务对象,然后再次调用它(在任何线程上)-应该是正常的-我们的调用没有并发性。httpclient在后台处理请求,并在请求完成后完成每个任务,或者2。在多个线程上重复调用client.getAsync(),而不等待每次返回任务对象。这是并发性,我怀疑这是开箱即用的支持。异步方法不能保证提供线程安全(案例2)。
- 后来,我想对@cwills发表评论。DefaultRequestHeaders就是默认值。如果在每个请求的基础上需要不同的头,可以创建新的StringContent(),在此基础上设置其他头,然后使用接受uri和httpContent的重载。
- httpclient每台服务器的默认最大连接数(HttpClientHandler.MaxConnectionsPerServer)也只有2个。请确保增加该值,否则多线程请求将被阻塞。
- 此外,要对线程请求设置不同的URI和头,您可以使用HttpRequestMessage并将其传递给SendAsync。
- 有人知道这个httpclient的singleton模式在将有多个用户的应用程序上使用服务器端是否安全吗?
- @查基,看这个:stackoverflow.com/a/40228347/1119545
这是一条关于HttpClient从亨利克F.尼尔森说:嘿。
"默认HttpClient是最简单的方式是你可以开始发送请求。一个单一的HttpClient可以用于发送HTTP请求。多为你想太多concurrently场景,你可以创建一个使用HttpClient,然后所有您的要求。"
- 如果用户名和密码可以在线程之间更改呢?这就是我找不到任何人谈论的问题
- @尼古拉斯迪皮亚扎:它多久改变一次?如果有一组已知的用户/密码对,那么您可以创建一个httpclient实例池。
- 是的,那就是我最后要做的
- 请注意,对所有请求重用相同的httpclient可能会导致过时的DNS问题:github.com/dotnet/corefx/issues/11224。
- @如果Ohadschneider认为该问题仅限于.NET核心。您可以通过向httpclient构造函数中插入自定义httpclienthandler,然后设置"connectionLeaseTimeout"来解决.NET 4的问题。但是,如果在100秒内没有向端点发送请求,则连接将自行刷新。protected override tasksendAsync(httpRequestMessage Request,CancellationToken CancellationToken)var sp=ServicePointManager.findServicePoint(Request.RequestUri);sp.ConnectionLeaseTimeout=100*1000;
一个后发现MSDN论坛(一个由亨利克·尼尔森HttpClient的首席建筑师)。
快速的总结:
- 如果你有一个请求是相关的(或不会步上彼此相同)然后使用HttpClient使得很多意义的。
- 一般我会建议在尽可能多的使用HttpClient的实例。