DownloadFileTaskAsync无法下载数千个文件

时间:2018-08-16 09:57:08

标签: c# webclient

我有数千个下载URL列表。网址可能包含其他类型的文件,例如图像,pdf,音频,视频等。我正在尝试使用DownloadFileTaskAsync下载它们。但是在下载了多个文件后,该应用程序崩溃了。我不明白发生了什么。没有收到任何错误消息。下载少量文件后,仅我的应用程序关闭。

foreach (var url in urls)
{
    //if file exists in our local directory then do not need to download and continue the process...
    if (FileExistsOrNot(localPath + "/" + url.fileName))
       continue;

    Thread thread = new Thread(async () => {
        WebClient client = new WebClient();
        client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
        client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
        await client.DownloadFileTaskAsync(new Uri(url.downloadUrl), localPath + "/" + url.fileName);  
    });
    thread.Start();
}

1 个答案:

答案 0 :(得分:1)

每次下载都会产生一个新线程,这也就怪不得您很快耗尽了系统资源(在这种情况下为线程)。

您应该使用某种线程池,幸运的是,C#有多种现成的解决方案可以做到这一点:

ThreadPool是最低级别的构造,并行编程和任务调度程序是在此之上构建的。

当您使用异步操作下载( DownloadFileTaskAsync )时,在这种情况下,任务是最合适的选项:

Action<string, DownloadProgressChangedEventArgs> onDownloadProgress = (url, e) => 
{ 
    /* your logic displaying progress... */ 
};

var downloadTasks = urls
    .Where(url => !FileExistsOrNot(Path.Combine(localPath, url.fileName)))
    .Select(async url =>
    {
        using (var client = new WebClient())
        {
            client.DownloadProgressChanged += (s, e) => onDownloadProgress(url.fileName, e);
            try { await client.DownloadFileTaskAsync(new Uri(url.downloadUrl), Path.Combine(localPath, url.fileName)); }
            catch (Exception ex) { /* handle download error: log exception, etc */ }                
        }
    });    

Task.WaitAll(downloadTasks.ToArray()); // or Task.WhenAll(...) if you want it non-blocking

一些评论:

  • 使用 Path.Combine 构建路径字符串以在每个平台上获得正确的结果
  • WebClient 实现 IDisposable ,即,它可以使用不受管理的资源。您不再需要它时,应立即对其调用 Dispose ,否则您可能会再次耗尽系统资源。
  • 您不需要遵守 DownloadFileCompleted 。等待 DownloadFileTaskAsync 会将潜在的错误作为异常重新抛出。
  • 考虑使用HttpClient代替WebClient以获得更好的异步支持和性能