.net core 是否应处置由HttpClientFactory创建的HttpClient实例?
因此,我已在我的Startup.cs中的服务集合中注册了一个命名客户端:.net core 是否应处置由HttpClientFactory创建的HttpClient实例?,.net-core,dotnet-httpclient,idisposable,asp.net-core-2.1,httpclientfactory,.net Core,Dotnet Httpclient,Idisposable,Asp.net Core 2.1,Httpclientfactory,因此,我已在我的Startup.cs中的服务集合中注册了一个命名客户端: services.AddHttpClient(someServiceName, client=>client.BaseAddress=BaseAddress); 现在可以从我的服务提供商处注入IHttpClientFactory 使用此IHttpClientFactory,我创建了一个客户端实例: var client=httpClientFactory.CreateClient(someServiceName) 曾几
services.AddHttpClient(someServiceName,
client=>client.BaseAddress=BaseAddress);
现在可以从我的服务提供商处注入IHttpClientFactory
使用此IHttpClientFactory
,我创建了一个客户端实例:
var client=httpClientFactory.CreateClient(someServiceName)
曾几何时,必须非常小心地处理HttpClient
实例
然而,现在我们有了HttpClientFactory
,这还重要吗?这个客户机是否应该/可以放心处置?e、 g
使用(var httpClient=httpClientFactory.CreateClient(someServiceName))
使用(var response=wait-httpClient.PostAsync(somePath,someData))
{
var content=wait response.content.ReadAsAsync();
//...
}
否。您不应处置您的客户。更一般地说,您不应该处理通过DI容器检索到的任何内容,在ASP.NET核心中,DI容器默认为服务集合。生存期是由DI容器管理的,因此,如果您处置了客户机,但随后将其注入到某个对象中,您将得到一个ObjectDisposedException
。让容器处理垃圾
这实际上是对IDisposable
类的常见混淆。如果您的类本身拥有依赖项,您个人应该只实现IDisposable
。如果注入了它的所有依赖项,则不应实现IDisposable
,因为它不拥有任何需要处理的内容。同样,您不应该处理注入类中的任何内容,因为它不拥有这些依赖项。只处理你特别新买的东西。如果您没有看到关键字new
,您可能不应该进行处理。调用Dispose
方法不是必需的,但是如果出于某些原因需要,您仍然可以调用它
证明:
不需要处置客户。Dispose取消传出请求,并保证在调用Dispose后无法使用给定的HttpClient实例。IHttpClientFactory跟踪和处置HttpClient实例使用的资源。HttpClient实例通常可以被视为不需要处理的.NET对象
检查:
公共HttpClient CreateClient(字符串名称)
{
if(name==null)
{
抛出新ArgumentNullException(nameof(name));
}
var handler=CreateHandler(名称);
var client=新的HttpClient(handler,disposeHandler:false);
var options=_optionsMonitor.Get(名称);
对于(var i=0;i
HttpMessageHandler
的实例存储HttpClient
的非托管资源。在经典场景中,HttpClient
创建HttpMessageHandler
的实例,并在自身进行处理时对其进行处理
您可以在上面的代码中看到,HttpClient
的不同实例共享HttpMessageHandler
的单个实例,并且不处理它(disposeHandler:false
)
因此,
HttpClient.Dispose
的调用不起任何作用。但这并不危险。查看这篇文章,它解释了factory@Nkosi如何处理客户机是的,我已经读过了。但是,我找到了一些与我问题中最后一个代码片段非常相似的代码,我想知道是否需要修复它。这有点让人困惑,因为客户端不是通过DI容器检索的。工厂是通过DI容器检索的。但是httpClientFactory.CreateClient(someServiceName)中的命名似乎暗示您需要重新创建工厂,所以这是令人困惑的部分。我和@kierenjohnstone在一起,资源是否更新并不重要,重要的是你是否控制了它的生命周期。在工厂的情况下,工厂进行实例化,它控制生命周期,而不是您。这就是重点。只处理属于您的资源。@ChrisPratt如果C#或.NET包含某种对象生存期和所有权的语义以防止这种混淆,您是否同意这一点?即使是简单的界面(例如IDisposableHahahNotReally
)或通过智能指针类型的对象引用对象,例如OwnedObject.Instance
和借用对象.Value
)。@ChrisPratt我认为这并不重要。我记得在一期关于ASP.NET回购协议的GitHub中读到,HttpClientHandler不能被处置。当您处置HttpClient(由如上所述的工厂创建)时,处理程序在处置HttpClient时“告诉”客户端不要处置它。因此,使用(var client=\u httpClientFactory.CreateClient()),这样的代码根本没有问题。(我想):)