等待Task.WhenAll似乎完成,但它永远不会到达下一行代码
问题描述:
我有一个简单的文件下载器,我从服务器获取一些文件,然后显示一条消息,通知它是成功还是失败。下面的代码:等待Task.WhenAll似乎完成,但它永远不会到达下一行代码
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)
断点,没有消息框显示等。有什么我在这里失踪?
答
由于死锁,断点从不碰撞if语句。将ConfigureAwait(false)添加到所有等待中。 EX-
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);
另一个optionto解决这个问题是,不使用等待或UI线程的结果。使用异步地等待着异常处理程序
EX-
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
放置代码,看看你得到一个异常 – jdweng
也许有些线程异常在你的代码中。注释掉“DownloadProgressChaged”和“DownloadFileCompleted”事件,看看它是否有效。如果有效,问题出在这些事件处理程序上。 – AjS
@jdweng我试过了,没有,它从来没有捕捉到任何东西,只是愉快地挂在WhenAll -AjS注释事件处理程序除了阻止相关的进度条工作之外没有任何作用 – Janushoff