正确的使用HttpClient

时间:2021-02-14 15:57:28

快捷的网络请求,多用HttpClient

但是常规的写法会一大片的TIME_OUT

比如这样的例子

        static async Task<string> TestHttpClient(string url)
        {
            using (var httpClient = new HttpClient())
            {
                var response = await httpClient.GetAsync(url);
                var context = response.Content;
                var result = await context.ReadAsStringAsync();

                return result;
            }
        }

HttpClient内部是线程安全的,所以可以改为

        static async Task<string> TestHttpClient(HttpClient httpClient, string url)
        {
            var response = await httpClient.GetAsync(url);
            var context = response.Content;
            var result = await context.ReadAsStringAsync();

            return result;
        }

但是很多场景下,这样却不方便~

那我们改一下

注入一个可以拿到单实例的HttpClient的接口,用这个接口就好了

    public interface IHttpClientSingle
    {
        HttpClient Single { get; }
    }

    internal class HttpClientSingle : IHttpClientSingle
    {
        public HttpClient Single { get; }

        public HttpClientSingle()
        {
            Single = new HttpClient();
        }
    }

在入口注入一下

services.AddSingleton<IHttpClientSingle, HttpClientSingle>();

需要HttpClient对象的地方就调用这个Single属性就好了

 

到这里是不是就搞定了,听闻.net core 2.1有个方案叫HttpClientFactory就解决这个问题呢?

它的本质是储存了一组HttpClientHandler,HttpClient构造方法里面,有一个重载的方法第一个参数传入,第二个参数置为False

参考地址:

DefaultHttpClientFactory.cs

代码行号124、125行

这个是我自己研究出来之后,再对照了一下实现,发现思路是一个

HttpClientHandler这个在.net core 2.0就有,更早版本就没追述了

到底是微软的坑,还是错误的用法的锅呢?陷入沉思

 

附上一组测试的代码

        static async void Test1(string url,int count)
        {
            using (var httpClientHandle = new HttpClientHandler())
            {
                for (int i = 0; i < count; i++)
                {
                    using (var httpClient = new HttpClient(httpClientHandle, false))
                    {
                        var response = await httpClient.GetAsync(url);
                        var context = response.Content;
                        var result = await context.ReadAsStringAsync();

                        Console.WriteLine($"{result}");
                    }
                }
            }

            Console.WriteLine("End");
        }