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

时间:2017-10-25 18:47:29

标签: c# asynchronous static task httpclient

我目前有一个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();
}

2 个答案:

答案 0 :(得分: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阻止,如果引发异常,则不会执行Disposeusing阻止Dispose即使是例外情况。

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

答案 1 :(得分:0)

Microsoft将HttpClient用作静态对象。即使每次都将其无效化的时间都是微不足道的,因为可能会出现其他问题。 他的链接包含一个简单的实现: https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client

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