使用 DownloadFileTaskAsync 一次下载所有文件 [英] Use DownloadFileTaskAsync to download all files at once

查看:36
本文介绍了使用 DownloadFileTaskAsync 一次下载所有文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定一个包含网址的输入文本文件,我想一次下载相应的文件.我用这个问题的答案UserState 使用 WebClient 和 TaskAsync 从异步 CTP 下载 as参考.

public void Run(){列表<字符串>urls = File.ReadAllLines(@"c:/temp/Input/input.txt").ToList();整数索引 = 0;任务[]任务=新任务[urls.Count()];foreach(网址中的字符串网址){WebClient wc = new WebClient();string path = string.Format("{0}image-{1}.jpg", @"c:/temp/Output/", index+1);任务 downloadTask = wc.DownloadFileTaskAsync(new Uri(url), path);任务 outputTask = downloadTask.ContinueWith(t => Output(path));任务[索引] = outputTask;}Console.WriteLine("现在开始");Task.WhenAll(任务);Console.WriteLine("完成");}公共无效输出(字符串路径){Console.WriteLine(路径);}

我预计文件的下载将在Task.WhenAll(tasks)"点开始.但结果是输出看起来像

<前>c:/temp/Output/image-2.jpgc:/temp/Output/image-1.jpgc:/temp/Output/image-4.jpgc:/temp/Output/image-6.jpgc:/temp/Output/image-3.jpg[删除了许多行]现在开始c:/temp/Output/image-18.jpgc:/temp/Output/image-19.jpgc:/temp/Output/image-20.jpgc:/temp/Output/image-21.jpgc:/temp/Output/image-23.jpg[删除了许多行]完毕

为什么在调用 WaitAll 之前就开始下载?我可以改变什么来实现我想要的(即所有任务将同时开始)?

谢谢

解决方案

为什么在调用 WaitAll 之前就开始下载?

首先,您不是在调用同步阻塞的 Task.WaitAll,而是在调用 Task.WhenAll,它返回一个应等待的可等待对象.

现在,正如其他人所说,当你调用一个异步方法时,即使没有使用 await ,它也会触发异步操作,因为任何符合 TAP 的方法都会返回一个热任务".

<块引用>

我可以改变什么来实现我想要的(即所有任务都会同时开始)?

现在,如果您想将执行推迟到 Task.WhenAll,您可以使用 Enumerable.Select 将每个元素投影到 Task,并在您将其传递给 Task.WhenAll 时将其具体化:

公共异步任务 RunAsync(){IEnumerableurls = File.ReadAllLines(@"c:/temp/Input/input.txt");var urlTask​​s = urls.Select((url, index) =>{WebClient wc = new WebClient();string path = string.Format("{0}image-{1}.jpg", @"c:/temp/Output/", index);var downloadTask = wc.DownloadFileTaskAsync(new Uri(url), path);输出(路径);返回下载任务;});Console.WriteLine("现在开始");等待 Task.WhenAll(urlTask​​s);Console.WriteLine("完成");}

Given a input text file containing the Urls, I would like to download the corresponding files all at once. I use the answer to this question UserState using WebClient and TaskAsync download from Async CTP as reference.

public void Run()
{
    List<string> urls = File.ReadAllLines(@"c:/temp/Input/input.txt").ToList();

    int index = 0;
    Task[] tasks = new Task[urls.Count()];
    foreach (string url in urls)
    {
        WebClient wc = new WebClient();
        string path = string.Format("{0}image-{1}.jpg", @"c:/temp/Output/", index+1);
        Task downloadTask = wc.DownloadFileTaskAsync(new Uri(url), path);
        Task outputTask = downloadTask.ContinueWith(t => Output(path));
        tasks[index] = outputTask;
    }
    Console.WriteLine("Start now");
    Task.WhenAll(tasks);
    Console.WriteLine("Done");

}

public void Output(string path)
{
    Console.WriteLine(path);
}

I expected that the downloading of the files would begin at the point of "Task.WhenAll(tasks)". But it turns out that the output look likes

c:/temp/Output/image-2.jpg
c:/temp/Output/image-1.jpg
c:/temp/Output/image-4.jpg
c:/temp/Output/image-6.jpg
c:/temp/Output/image-3.jpg
[many lines deleted]
Start now
c:/temp/Output/image-18.jpg
c:/temp/Output/image-19.jpg
c:/temp/Output/image-20.jpg
c:/temp/Output/image-21.jpg
c:/temp/Output/image-23.jpg
[many lines deleted]
Done

Why does the downloading begin before WaitAll is called? What can I change to achieve what I would like (i.e. all tasks will begin at the same time)?

Thanks

解决方案

Why does the downloading begin before WaitAll is called?

First of all, you're not calling Task.WaitAll, which synchronously blocks, you're calling Task.WhenAll, which returns an awaitable which should be awaited.

Now, as others said, when you call an async method, even without using await on it, it fires the asynchronous operation, because any method conforming to the TAP will return a "hot task".

What can I change to achieve what I would like (i.e. all tasks will begin at the same time)?

Now, if you want to defer execution until Task.WhenAll, you can use Enumerable.Select to project each element to a Task, and materialize it when you pass it to Task.WhenAll:

public async Task RunAsync()
{
    IEnumerable<string> urls = File.ReadAllLines(@"c:/temp/Input/input.txt");

    var urlTasks = urls.Select((url, index) =>
    {
        WebClient wc = new WebClient();
        string path = string.Format("{0}image-{1}.jpg", @"c:/temp/Output/", index);

        var downloadTask = wc.DownloadFileTaskAsync(new Uri(url), path);
        Output(path);

        return downloadTask;
    });

    Console.WriteLine("Start now");
    await Task.WhenAll(urlTasks);
    Console.WriteLine("Done");
}

这篇关于使用 DownloadFileTaskAsync 一次下载所有文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆