c# - 如何确保我的 HttpClient 在 C# 中只初始化一次?

标签 c# concurrency dotnet-httpclient

根据 Microsoft 的指南,我希望通过仅拥有 HttpClient pr 的单个实例来确保正确使用 HttpClient。 API 消耗。我对我的解决方案能否正常工作感到有点厌倦

我尝试在创建函数周围添加一个锁,如果静态变量为空,该函数就会被调用。

    public class BaseClient
    {
        private static volatile HttpClient _httpClient;
        private static readonly object HttpClientLock = new object();

        public BaseClient(string serviceAddress, string apiKeyRequestHeader, string apiKeyValue)
        {
            CreateClient(serviceAddress, apiKeyValue, apiKeyRequestHeader);
        }

        private void CreateClient(string baseAddress, string apiKeyRequestHeaderValue, string apiKeyRequestHeader)
        {
            if (_httpClient == null)
            {
                lock (HttpClientLock)
                {
                    if (_httpClient == null)
                    {
                        _httpClient = new HttpClient
                        {
                            BaseAddress = new Uri(baseAddress)
                        };

                        _httpClient.DefaultRequestHeaders.Accept.Add(
                            MediaTypeWithQualityHeaderValue.Parse("application/json"));
                        if (!string.IsNullOrEmpty(apiKeyRequestHeaderValue))
                            _httpClient.DefaultRequestHeaders.Add(apiKeyRequestHeader, apiKeyRequestHeaderValue);
                        _httpClient.Timeout = new TimeSpan(0, 3, 0);
                    }
                }
            }
        }
    }

我想确保 HttpClient 只为每个类实例化一次,这样我就不会在套接字的使用中溢出。这段代码能保证这种情况发生吗?

最佳答案

确保只有一个 HttpClient 实例的最简单方法是利用默认情况下线程安全的静态初始化(由框架保证),post 中有很好的解释。关于 C# 中可能的单例实现。

按照示例,您可以通过避免锁来简化代码:

public class BaseClient
{
    private static readonly HttpClient _httpClient = new HttpClient();

    static BaseClient()
    {
    }

    public BaseClient(string serviceAddress, string apiKeyRequestHeader, string apiKeyValue)
    {
        InitializeClient(serviceAddress, apiKeyValue, apiKeyRequestHeader);
    }

    private void InitializeClient(string baseAddress, string apiKeyRequestHeaderValue, string apiKeyRequestHeader)
    {
        _httpClient.BaseAddress = new Uri(baseAddress);
        _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        _httpClient.Timeout = TimeSpan.FromMinutes(3);

        if (!string.IsNullOrEmpty(apiKeyRequestHeaderValue))
        {
            _httpClient.DefaultRequestHeaders.Add(apiKeyRequestHeader, apiKeyRequestHeaderValue);
        }
    }
}

除此之外,您始终可以测试您的方法并检查是否可以同时拥有多个实例。

注意: 当 DNS changes 时,拥有一个 HttpClient 实例可能会导致问题。如果您使用 .Net Core,那么您应该使用 HttpClientFactory 来代替,因为 Microsoft 在那里解决了问题。

关于c# - 如何确保我的 HttpClient 在 C# 中只初始化一次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57803789/

相关文章:

c# - 如何在 .NET 3.5 中通过 NamedPipe 发送对象?

c# - RegEx.Replace 失败,替换字符串为 $0.00

Java Executor 在上一个 Callable 完成后执行一个 Callable?

c# - 为什么不调用 Task<T>.Result 死锁?

silverlight - 无法将 System.Net.Http 包安装到 Windows Phone 7.1 Silverlight 项目中

c# - Linq 从另一个区间列表中选择任何区间内的所有数字

java - 新的SingleThreadscheduledExecutor

concurrency - Io 语言如何自动检测死锁?

c# - 如何通过 REST api 在 JIRA 中创建问题?

c# - 林克 : select value in a datatable column