0

I have a problem downloading the file in my c# code.

public Form1()
{
    InitializeComponent();

    DownloadFile().Wait();
}
private async Task DownloadFile()
{
    Debug.WriteLine("Download");// appears
    HttpClient client = new();
    var response = await client.GetAsync("file");
    Debug.WriteLine("End download");// does not display
}

Thread stop after download but the app is not showing.

Le thread 0x7d28 s'est arrêté avec le code 0 (0x0).
Le thread 0x7998 s'est arrêté avec le code 0 (0x0).
Le thread 0x269c s'est arrêté avec le code 0 (0x0).
Le thread 0x7e74 s'est arrêté avec le code 0 (0x0).
Le thread 0x534c s'est arrêté avec le code 0 (0x0).
Le thread 0x77f0 s'est arrêté avec le code 0 (0x0).
Le thread 0x70fc s'est arrêté avec le code 0 (0x0).
Le thread 0x7428 s'est arrêté avec le code 0 (0x0).
Le thread 0x5628 s'est arrêté avec le code 0 (0x0).
Le thread 0x788c s'est arrêté avec le code 0 (0x0).
Le thread 0x63f4 s'est arrêté avec le code 0 (0x0).

Clément
  • 9
  • 1
  • 1
  • 1
    Don't use `Wait()`. Use `await`. You can't use `await` in the constructor, but you can use it in `Form_Load`. See [this answer](https://stackoverflow.com/a/13140963/2791540) – John Wu Oct 15 '22 at 23:07
  • Don't use `Wait()` or `Result` in WinForms. Don't call that method from the Constuctor, subscribe to the `Load` event, make the handler `async` then `await DownloadFile()` -- Declare the HttpClient object as a static Field, dispose of it when the Form closes – Jimi Oct 15 '22 at 23:09

2 Answers2

0

don't use async / await in combination with Wait() or Result, because it will result in a deadlock.

To avoid a deadlock within a SynchronizationContext, you should use ConfigureAwait(false):

private async Task DownloadFile()
{
    Debug.WriteLine("Download");// appears
    HttpClient client = new();
    var response = await client.GetAsync("file").ConfigureAwait(false);
    Debug.WriteLine("End download");// does not display
}
Nobody
  • 149
  • 5
0

Classic HttpClient bug. When waited on the main thread causes deadlock. ConfigureAwait(false) that exist to resolve this type of problem don't work with HttpClient...

To doge this, you need to force the http call on a other thread. To do this, you can encapsulate the http call in a task like :

private async Task DownloadFile()
{
    Debug.WriteLine("Download");
    HttpClient client = new();
    var response =  await Task.Run(() =>await client.GetAsync("file"));
    Debug.WriteLine("End download");
}

From .NET 5, HttpClient has (finaly) synchronous method :

private void DownloadFile()
{
    Debug.WriteLine("Download");
    HttpClient client = new();
    var response = client.Get("file");
    Debug.WriteLine("End download");
}

But it's a bad practice to do heavy work in a constructor or on the main thread for UI program. Maybe you can consider to use Form.Load event.

vernou
  • 6,818
  • 5
  • 30
  • 58