是否应该处理由HttpClientFactory创建的HttpClient实例?

时间:2018-06-18 14:49:21

标签: .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)

曾几何时,有必要非常小心处理HttpClient个实例,因为它是rarely the right thing to do

但是,现在我们已经HttpClientFactory,这是否重要了?这个client应该/可以毫无顾虑地处理吗? e.g。

using (var httpClient = httpClientFactory.CreateClient(someServiceName))
using (var response = await httpClient.PostAsync(somePath, someData))
{
    var content = await response.Content.ReadAsAsync<SomeResponse>();
    //...
}

2 个答案:

答案 0 :(得分:9)

没有。你不应该处置你的客户。更一般地说,你不应该处理通过DI容器检索的任何,在ASP.NET Core中默认是服务集合。生命周期由DI容器管理,因此如果您丢弃客户端,但稍后将其注入某个内容,您将获得ObjectDisposedException。让容器处理掉。

这实际上是IDisposable类的常见混淆。如果您的类本身拥有依赖项,您应该亲自实现IDisposable。如果所有依赖项都是注入,则不应实现IDisposable,因为它不拥有任何需要处理的东西。同样,你不应该处理注入你班级的任何东西,因为它不拥有这些依赖关系。只处理你特别新的东西。如果您没有看到关键字new,那么您可能不应该处置。

答案 1 :(得分:3)

不需要调用Dispose方法,但是由于某些原因,您仍然可以调用它。

证明:HttpClient and lifetime management

  

不需要处理客户端。 Disposal取消传出的请求,并确保在调用Dispose之后不能使用给定的HttpClient实例。 IHttpClientFactory跟踪并处置HttpClient实例使用的资源。 HttpClient实例通常可以视为不需要处理的.NET对象。

检查source of DefaultHttpClientFactory

public HttpClient CreateClient(string name)
{
    if (name == null)
    {
        throw new ArgumentNullException(nameof(name));
    }

    var handler = CreateHandler(name);
    var client = new HttpClient(handler, disposeHandler: false);

    var options = _optionsMonitor.Get(name);
    for (var i = 0; i < options.HttpClientActions.Count; i++)
    {
        options.HttpClientActions[i](client);
    }

    return client;
}

HttpMessageHandler的实例存储HttpClient的非托管资源。在经典方案中,HttpClient创建HttpMessageHandler的实例,并在其自身处置时对其进行处置。

您可以在上面的代码中看到HttpClient的不同实例共享HttpMessageHandler的单个实例,并且没有对其进行处置(disposeHandler: false)。

因此,HttpClient.Dispose的调用没有任何作用。但这并不危险。