Static HttpClient is thread safe on ASP.net HttpRequest

We are creating a wrapper for the HttpClient. As we will follow performance optimization recommendations from https://github.com/mspnp/performance-optimization . We want to avoid the anti-template - the wrong instance mentioned in this document. I passed this guide to my team in order to use the static HttpClient. The feedback I received is regarding thread safety. Each request has a header containing the user's request. Since I have a static HttpClient, will it be thread safe? If we have several requests hitting the code (for example, GET) at the same time, will the race condition set the title? We have an implementation as shown below.

public class HttpClientHelper{ private static readonly HttpClient _HttpClient; static HttpClientHelper() { HttpClient = new HttpClient(); HttpClient.Timeout = TimeSpan.FromMinutes(SOME_CONFIG_VALUE); } public async Task<HttpResponseMessage> CallHttpClientPostAsync(string requestUri, HttpContent requestBody) { AddHttpRequestHeader(httpClient); var response = await httpClient.PostAsync(requestUri, requestBody); //Potential thread synchronization issue??? return response; } public HttpResponseMessage CallHttpClientGet(string requestUri) { AddHttpRequestHeader(httpClient); var response = httpClient.GetAsync(requestUri).Result; //Potential thread synchronization issue??? return response; } private void AddHttpRequestHeader(HttpClient client) { string HeaderName = "CorrelationId"; client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(Properties.Settings.Default.HttpClientAuthHeaderScheme, GetTokenFromClaims()); //Race condition??? if (client.DefaultRequestHeaders.Contains(HeaderName)) client.DefaultRequestHeaders.Remove(HeaderName); client.DefaultRequestHeaders.Add(HeaderName, Trace.CorrelationManager.ActivityId.ToString()); } 

}

+7
thread-safety static-libraries
source share
1 answer

Your team is correct; it is far from safe for threads. Consider this scenario:

  • Thread A sets the CorrelationId header to "foo".
  • Thread B sets the CorrelationId header to "bar".
  • Sends a Thread A request that contains thread B CorrelationId.

It is better to approach your CallXXX methods to create new HttpRequestMessage objects and set a title to them and use HttpClient.SendAsync to make the call.

Keep in mind that reusing HttpClient instances is only useful if you are making multiple calls to the same host.

+10
source

All Articles