Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

await Task.WhenAll seemingly completes, but it never reaches next line of code

I have a simple file downloader, where I get some files from a server, and then display a message informing whether it succeeded or failed. Here's the code:

public async Task GetFiles(IEnumerable<string> urlList)
{
    //some variable declaring, setting etc.

    await Task.WhenAll(urlList.Select(url => Task.Run(() => DownloadFile(url, dir, count++))).ToList());
    //problem lies here, the WhenAll never completes
    if (fileDownloadError)
    {
        Directory.Delete(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "downloads"));
        MessageBox.Show("Fail");
        return;
    }
    MessageBox.Show("Success");
}

internal async Task DownloadFile(string url, string dir, int count)
{
    string filename = HelperClass.GetFilenameFromUrl(url);
    long a = 0;
    newList.Add(a);
    using (var client = new WebClient())
    {
        TempDownload tp = new TempDownload()
        {
            id = count
        };

        client.DownloadProgressChanged += new DownloadProgressChangedEventHandler((sender, e) => ProgressChanged(sender, e, tp));
        client.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);

        await client.DownloadFileTaskAsync(url, string.Concat(dir, "\\", filename));
    }
}

The ProgressBar I change in DownloadProgressChanged event goes to 100%, the files are properly downloaded, yet the code after the WhenAll never executes, that is it never hits the breakpoint on if (fileDownloadError), no MessageBox is shown etc. Is there something I'm missing here?

like image 491
Janushoff Avatar asked Oct 15 '25 11:10

Janushoff


1 Answers

Breakpoint never hits if statement because of deadlock. Add ConfigureAwait(false) to all the awaits. Ex-

await Task.WhenAll(urlList.Select(url => Task.Run(() => DownloadFile(url, dir, count++))).ToList()).ConfigureAwait(false);

and also

await client.DownloadFileTaskAsync(url, string.Concat(dir, "\\", filename)).ConfigureAwait(false);

Another optionto solve this is, to not use Wait or Result on UI thread. Use async await

ex-

private async void button1_Click(object sender, EventArgs e)
{
            await GetFiles();
}    

For detail,

https://msdn.microsoft.com/en-us/magazine/gg598924.aspx

https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

like image 76
Kaushal Avatar answered Oct 18 '25 02:10

Kaushal



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!