可重用的 HttpClient 实例与静态变量(在多个线程中大量使用)?

Posted

技术标签:

【中文标题】可重用的 HttpClient 实例与静态变量(在多个线程中大量使用)?【英文标题】:Reusable HttpClient instance vs static variable (Heavily used in multiple threads)? 【发布时间】:2017-10-25 18:47:28 【问题描述】:

我目前有一个HttpClient 的实例变量,它在实例方法中用于下载图像。该方法总是在Task.Run() 中调用。 此方法可以在一分钟内调用数千次,并且不会崩溃或产生任何错误。但我只是想知道如果我切换到 static HttpClient 会有什么好处(如果有的话),除了可能更安全之外。

这里有一些上下文代码:

HttpClient client = new HttpClient(); // Make this static?

// Always called in a Task.Run(() => DownloadImage(Obj));
public async void DownloadImage(Object obj)

    FormUrlEncodedContent formContent = GetFormContent(Obj);
    HttpResponseMessage Result = await client.PostAsync("URL", formContent).ConfigureAwait(false);
    byte[] Data = Result.Content.ReadAsByteArrayAsync().Result;
    StaticClass.Images[Obj.ID] = ImageSource.FromStream(() => new MemoryStream(Data));
    formContent.Dispose();
    Result.Dispose();

【问题讨论】:

如果 DownloadImage 被调用在这个代码所在的任何类的同一个实例上,那么没有区别 @Jonesopolis 是的,就是这样。 有谁知道什么时候适合制作一个经常重用的静态 HttpClient ?这篇文章建议这样做:aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong HttpClient is fully thread-safe and reentrant,因此将其设为静态变量实际上是与其交互的首选方式。 什么是temp?为什么不是你的DownloadImage async 【参考方案1】:

由于您没有使用async 版本并且您正在调用ReadAsByteArrayAsync().Result,因此您很可能会陷入死锁。

推荐

以下是最推荐的方式,

static HttpClient client = new HttpClient ();

public async Task DownloadImage(Object obj)

    using(FormUrlEncodedContent formContent = GetFormContent(Obj)) 
       using(HttpResponseMessage Result = await 
           client.PostAsync("URL", formContent)
           .ConfigureAwait(false))
              byte[] Data = await Result.Content.ReadAsByteArrayAsync();
              StaticClass.Images[Obj.ID] = ImageSource.FromStream(
                   () => new MemoryStream(Data));
        
    


同样不要调用Dispose,使用using块,如果抛出异常,Dispose将不会被执行,using块将正确Dispose即使出现异常。

只要所有一次性用品都包裹在using 中,async await 使用得当,HttpClient 将在单个静态实例中表现最佳。

【讨论】:

【参考方案2】:

HttpClient 被微软用作静态对象。即使每次启动它的时间都很短,因为可能会出现其他问题。 他的链接包含一个简单的实现: https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client.

由于您将在更多情况下使用客户端而不是简单地获取图像,因此我建议您使用具有静态方法(如果可能的话,异步)的类用于 get/post/put/delete,您将在其中动态插入方法名称和对象.

【讨论】:

以上是关于可重用的 HttpClient 实例与静态变量(在多个线程中大量使用)?的主要内容,如果未能解决你的问题,请参考以下文章

C#HttpClient高并发时怎么解决TCP连接数过多

读函数式编程思维笔记04_语言与范式_模式与重用

为不同的用户重用 HttpClient

具有不同身份验证标头的 HttpClient 单个实例

Java静态方法,静态变量,初始化顺序

重新使用 HttpClient 但每个请求的超时设置不同?