等待Task.WhenAll似乎完成了,但它永远不会到达下一行代码

时间:2017-04-19 09:55:14

标签: c# task multitasking

我有一个简单的文件下载程序,我从服务器获取一些文件,然后显示一条消息,通知它是成功还是失败。这是代码:

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));
    }
}

我在ProgressBar事件中的DownloadProgressChanged更改为100%,文件已正确下载,但WhenAll之后的代码从未执行,也就是说它从未到达断点if (fileDownloadError),没有显示MessageBox等。我在这里找不到什么东西?

1 个答案:

答案 0 :(得分:4)

由于死锁,断点永远不会命中if语句。将ConfigureAwait(false)添加到所有等待中。前 -

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

以及

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

解决此问题的另一个选择是,不要在UI线程上使用Wait或Result。使用async await

前 -

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

详细信息,

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

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