如何同时正确下载文件?

How to download correctly files simultaneously?

我正在尝试同时下载多个文件。但是所有文件都在一个接一个地下载。所以,首先下载这个文件@"http://download.geofabrik.de/europe/cyprus-latest.osm.pbf",然后开始下载这个文件@"http://download.geofabrik.de/europe/finland-latest.osm.pbf",,下一个要下载的文件是@"http://download.geofabrik.de/europe/great-britain-latest.osm.pbf"等等。

但是我想同时下载

所以我有以下基于the code from this answer的代码:

static void Main(string[] args)
{
    Task.Run(async () =>
    {
        await DownloadFiles();
    }).GetAwaiter().GetResult();
}

public static async Task DownloadFiles()
{
    IList<string> urls = new List<string>
    {
        @"http://download.geofabrik.de/europe/cyprus-latest.osm.pbf",
        @"http://download.geofabrik.de/europe/finland-latest.osm.pbf",
        @"http://download.geofabrik.de/europe/great-britain-latest.osm.pbf",
        @"http://download.geofabrik.de/europe/belgium-latest.osm.pbf",
        @"http://download.geofabrik.de/europe/belgium-latest.osm.pbf"
    };

    foreach (var url in urls)
    {
        string fileName = url.Substring(url.LastIndexOf('/'));
        await DownloadFile(url, fileName);
    }            
}

public static async Task DownloadFile(string url, string fileName)
{
    string address = @"D:\Downloads";
    using (var client = new WebClient())
    {
        await client.DownloadFileTaskAsync(url, $"{address}{fileName}");
    }
}

但是,当我在我的文件系统中查看时,我看到文件正在一个接一个地按顺序下载, 不是同时下载:

此外,我尝试使用this approach,但是没有同时下载:

static void Main(string[] args)
{
    IList<string> urls = new List<string>
    {
        @"http://download.geofabrik.de/europe/cyprus-latest.osm.pbf",
        @"http://download.geofabrik.de/europe/finland-latest.osm.pbf",
        @"http://download.geofabrik.de/europe/great-britain-latest.osm.pbf",
        @"http://download.geofabrik.de/europe/belgium-latest.osm.pbf",
        @"http://download.geofabrik.de/europe/belgium-latest.osm.pbf"
    };

    Parallel.ForEach(urls,
        new ParallelOptions { MaxDegreeOfParallelism = 10 },
        DownloadFile);
}

public static void DownloadFile(string url)
{
    string address = @"D:\Downloads";
    using (var sr = new StreamReader(WebRequest.Create(url)
           .GetResponse().GetResponseStream()))
    using (var sw = new StreamWriter(address + url.Substring(url.LastIndexOf('/'))))
    {
        sw.Write(sr.ReadToEnd());
    }
}

能告诉我如何同时下载吗?

如有任何帮助,我们将不胜感激。

    foreach (var url in urls)
    {
        string fileName = url.Substring(url.LastIndexOf('/'));
        await DownloadFile(url, fileName); // you wait to download the item and then move the next
    }   

相反,您应该创建任务并等待所有任务完成。

public static Task DownloadFiles()
{
    IList<string> urls = new List<string>
    {
        @"http://download.geofabrik.de/europe/cyprus-latest.osm.pbf",
        @"http://download.geofabrik.de/europe/finland-latest.osm.pbf",
        @"http://download.geofabrik.de/europe/great-britain-latest.osm.pbf",
        @"http://download.geofabrik.de/europe/belgium-latest.osm.pbf",
        @"http://download.geofabrik.de/europe/belgium-latest.osm.pbf"
    };

       var tasks = urls.Select(url=> {
           var fileName = url.Substring(url.LastIndexOf('/'));
             return DownloadFile(url, fileName);    
         }).ToArray();   
         return Task.WhenAll(tasks);       
}

其余代码可以保持不变。

这将一个接一个地异步下载它们。

await DownloadFile(url, fileName);
await DownloadFile(url2, fileName2);

这将实现您实际想要实现的目标:

var task1 = DownloadFile(url, fileName);
var task2 = DownloadFile(url2, fileName2);
await Task.WhenAll(task1, task2);

Eldar 的解决方案需要一些小的修改。这是已编辑的完整工作 DownloadFiles 方法:

public static async Task DownloadFiles()
{
    IList<string> urls = new List<string>
{
    @"http://download.geofabrik.de/europe/cyprus-latest.osm.pbf",
    @"http://download.geofabrik.de/europe/finland-latest.osm.pbf",
    @"http://download.geofabrik.de/europe/great-britain-latest.osm.pbf",
    @"http://download.geofabrik.de/europe/belgium-latest.osm.pbf",
    @"http://download.geofabrik.de/europe/belgium-latest.osm.pbf"
};

    var tasks = urls.Select(t => {
        var fileName = t.Substring(t.LastIndexOf('/'));
        return DownloadFile(t, fileName);
    }).ToArray();   

    await Task.WhenAll(tasks);
}