Search code examples
c#async-awaitdotnet-httpclient

C# HttpClient PostAsync blocks forever


I have a strange behavior that I can't manage to explain. In an async function, an awaited call blocks forever.

Note: it seams that the problem occurs since I moved from a console app to a Windows Form. (the call is called from the constructor of Form1(). _client is the HttpClient dotnet class.

 public async Task GetConfigurationFile()
 {
       var stringContent = new StringContent(JsonConvert.SerializeObject(companyKey), Encoding.UTF8, "application/json");
       HttpResponseMessage response = null;

       // This call works and returns the respons after a few milliseconds
       response = _client.PostAsync(_configurationFileEndpoint, stringContent).Result;

       // The same awaited call block forever and never returns.
       response = await _client.PostAsync(_configurationFileEndpoint, stringContent);           
 }

  public Form1()
  {
        InitializeComponent();
        _engine = new Engine();
  }

 public Engine()
    {
        // Logic similar to this.
        Configuration configuration = null;
        try
        {
            using (var reader = new StreamReader(Directory.GetCurrentDirectory() + "/configuration.json"))
            {
                configuration = Newtonsoft.Json.JsonConvert.DeserializeObject<Configuration>(reader.ReadToEnd());
            }
        }
        catch (Exception ex)
        { 
               // Something done
        }
        _apiCall = new PlatformCommunication(configuration);

        if (configuration == null)
        {               
            try
            {
                _apiCall.GetConfigurationFile().Wait();
            }
            catch (Exception exc)
            {

            }
        }
    }

Solution

  • @YK1: to prevent blocking calls, I can move the code in the constructor of Engine() to an Async Initialize function and await _apiCall.GetConfigurationFile() instead of_apiCall.GetConfigurationFile().Wait(); But then in my Winform, I need to await engine.Initialize() from an Async function which I don't have? ( engine must run automatically, not be behind a start button), reason why I put it in the constructor of the form which is not async.

    Instead of constructor, move your startup code code to an async method. You can subscribe to Form_Load event and call that method.

    class Engine 
    {
    
        public async Task Init()
        {
            // Logic similar to this.
            Configuration configuration = null;
            try
            {
                using (var reader = new StreamReader(Directory.GetCurrentDirectory() + "/configuration.json"))
                {
                    configuration = Newtonsoft.Json.JsonConvert.DeserializeObject<Configuration>(reader.ReadToEnd());
                }
            }
            catch (Exception ex)
            { 
                   // Something done
            }
            _apiCall = new PlatformCommunication(configuration);
    
            if (configuration == null)
            {               
                try
                {
                    await _apiCall.GetConfigurationFile();
                }
                catch (Exception exc)
                {
    
                }
            }
        }
    }
    

    and

    private async void Form_Load(object sender, EventArgs e)
    {
        _engine = new Engine();
        await _engine.Init();
    }