同时下载多个文件,并在所有文件下载完成后继续

时间:2014-01-28 08:06:48

标签: c# .net task-parallel-library

我们正在编写一个小工具,从我们的Web服务器下载文件并对其进行分析。这是一个很多文件,下载大约需要10分钟,我们希望通过允许应用程序并行下载文件来缩短下载时间。

目前我们有一个循环遍历要下载的文件列表,只需下载它们并将文件名添加到分隔的字符串中:

foreach (var File in ServerFiles)
{
    string sFileName = File.Uri.LocalPath.ToString();
    // some internal logic and initialization 
    oBlob.DownloadToStream(fileStream);
    sFiles += sFileName.Replace("/" + Container + "/", "") + ",";
}

我们已将其更改为:

foreach (var File in ServerFiles)
{
    string sFileName = File.Uri.LocalPath.ToString();
    // some internal logic and initialization 
    Task downloadTask = oBlob.DownloadToStreamAsync(fileStream);
    sFiles += sFileName.Replace("/" + Container + "/", "") + ",";
}

现在我的问题是如何处理我回来的任务。如果我只是调用downloadTask.wait()那么它将像以前一样离开它。

我考虑过使用continueWith - 但是该块内应该做什么?怎么知道所有其他文件都已完成下载?

我甚至考虑过在一个集合中存储任务,并在foreach循环结束时编写另一个循环,它接受所有任务并调用wait方法。

解决此类问题的正确方法是什么?

2 个答案:

答案 0 :(得分:2)

您可以将所有任务存储在集合中,然后调用 Task.WaitAll(yourArray); 在完成所有任务之前,您的代码将被阻止。 像这样:

var tasks=new List<Task>();
foreach (var File in ServerFiles)
{
    string sFileName = File.Uri.LocalPath.ToString();
    // some internal logic and initialization 
    Task downloadTask = oBlob.DownloadToStreamAsync(fileStream);
tasks.Add(downloadTask);
    sFiles += sFileName.Replace("/" + Container + "/", "") + ",";
}
Task.WaitAll(tasks);
//Continue here

答案 1 :(得分:1)

我会使用Parallel.Foreach使用单独的线程下载所有文件。

除非你真的需要/想要将所有下载的文件连接成一个大字符串,(并编写逻辑以便以后检索单个文件),否则我将字符串存储在线程安全列表中(sush as System.Collections.Concurrent .ConcurrentBag允许多个线程写入列表)。

ConcurrentBag<string> downloadedFiles = new ConcurrentBag<string>();

Parallel.ForEach(ServerFiles, file =>
{
    string sFileName = file.Uri.LocalPath.ToString();
    // some internal logic and initialization 
    oBlob.DownloadToStream(fileStream);
    downloadedFiles.Add(sFileName);
});