Multiple HttpClient without freezing

Jassim Al Rahma 1,586 Reputation points
2022-10-25T12:46:19.77+00:00

Hi,

I have the following code block:

foreach (var mydata in THE_DATA)  
{  
    var client = new HttpClient();  
    client.BaseAddress = new Uri("https://my.domain.com/create.php");  
  
    var content = new FormUrlEncodedContent(new[]  
    {  
        new KeyValuePair<string, string>("source_uuid", "source_uuid"),  
    });  
  
    var response = await client.PostAsync("https://my.domain.com/create.php", content);  
    var result = await response.Content.ReadAsStringAsync();  
    List<MyData> data = JsonSerializer.Deserialize<List<MyData>>(result);  
  
    my_id = data[0].my_id;  
  
    foreach (var first in mydata.first)  
    {  
        var first_client = new HttpClient();  
  
        first_client.BaseAddress = new Uri("https://www.domain.com/first.php");  
  
        var first_content = new FormUrlEncodedContent(new[]  
        {  
            new KeyValuePair<string, string>(“my_id”, my_id),  
            new KeyValuePair<string, string>("first", first.name)  
        });  
  
        var first_response = await client.PostAsync("https://www.domain.com/first.php", first_content);  
    }  
  
    foreach (var second in mydata.second)  
    {  
        var second_client = new HttpClient();  
  
        second_client.BaseAddress = new Uri("https://www.domain.com/second.php");  
  
        var second_content = new FormUrlEncodedContent(new[]  
        {  
            new KeyValuePair<string, string>(“my_id”, my_id),  
            new KeyValuePair<string, string>("second", second.name)  
        });  
  
        var second_response = await client.PostAsync("https://www.domain.com/second.php", second_content);  
    }  
}  

How can I ensure it’s running smoothly on my .NET MAUI app without killing the app performance and without my app getting freezes?

Kindly advise..

Thanks,
Jassim

.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
3,696 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
11,093 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Michael Taylor 55,301 Reputation points
    2022-10-25T15:04:10.08+00:00

    You shouldn't be creating HttpClient instances at random. The client will grab a random port to use and once it has the port that port (because of TCP keep alive) will not be released back anytime soon. Hence when you get to 64K client instantiations (or more likely less) you'll start running into errors.

    @AgaveJoe linked to the docs that discuss how to do this properly. For each unique URL domain (not URL within the domain) you can create a separate HttpClient once per app instance. The client is thread safe provided you're not setting default headers. Configure the root client in app startup as part of your DI setup. Then use DI to get the client when you need it. If you need multiple HttpClient instances pointing to different base URLs then register multiple instances by name so you can select the correct one as needed. Do not dispose of the client when you're done with it.

       //App startup  
       void ConfigureServices ( IServiceCollection services )  
       {  
          //If you only need 1 HttpClient then use the simple version  
          services.AddHttpClient("MyClient")  
                      .ConfigureHttpClient(c => {  
                            c.BaseAddress = new Uri("https://mydomain.com/");  
                       });  
         
          //Register services that rely on the named client  
          services.AddScoped<MyService>(provider => {  
                     var factory = provider.GetRequiredService<IHttpClientFactory();  
                     var client = CreateClient("MyClient");  
         
                     return new MyService(client);  
           });  
       }  
         
       //Your code  
       public class MyService  
       {  
          public MyService ( HttpClient client )  
          {  
              _client = client;  
          }  
         
          //Your original code  
          public async Task DoWork ()  
          {  
             foreach (var mydata in THE_DATA)  
             {  
                 client.BaseAddress = new Uri("https://my.domain.com/create.php");  
         
                 List<MyData> data = null;  
         
                 using var content = new FormUlrEncodedContent(...);  
                 using (var response = _client.PostAsync("create.php", content))  
                 {  
                    data = await response.Content.ReadFromJsonAsync<List<MyData>();     
                    my_id = data[0].my_id;  
                 };  
             
                 foreach (var first in mydata.first)  
                 {                        
                    using var content = new FormUrlEncodedContent(...);      
                    using (var response = await _client.PostAsync("first.php", content))  
                    {                    
                    };  
                 };  
                 ...      
          }  
         
          private readonly HttpClient _client;  
       }  
    

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.