Jim Layhey
Jim Layhey

Reputation: 363

Reusable HttpClient instance vs static variable (Heavily used in multiple threads)?

I currently have an instance variable of a HttpClient which is used in an instance method to download an image. The method is always called in a Task.Run(). This method can be called thousands of times in a minute and doesn't crash or produce any errors. But I just wanted to know what benefits, if any, there would be if I switched to a static HttpClient, apart from perhaps being more thread safe.

Here is some code for context:

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();
}

Upvotes: 6

Views: 8379

Answers (2)

Angelos p
Angelos p

Reputation: 1

HttpClient is intented by microsoft to be used as a static object. Even if the time to instatiate it every time is trivial, because other issues could arise. his link contains a simple implementation : https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client .

Since you will be using the client in more more cases than simple getting an image I would suggest a class with static methods (async if you may) for get/post/put/delete where you would inserting method names and objects dynamically.

Upvotes: 0

Akash Kava
Akash Kava

Reputation: 39916

No

Since you are not using async version and you are calling ReadAsByteArrayAsync().Result you will most likely end up in deadlocks.

Recommended

Following is the most recommended way,

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));
        }
    }

}

Also don't call Dispose, use using block, Dispose will not be executed if an exception is thrown, using block will properly Dispose even in case of exception.

As long as, all disposables are wrapped in using and async await are used properly, HttpClient will perform best with single static instance.

Upvotes: 2

Related Questions