给定一个包含 URL 的输入文本文件,我想一次性下载所有相应的文件。我用这个问题的答案使用 WebClient 和 TaskAsync 从异步 CTP 下载 UserState https://stackoverflow.com/questions/11579928/userstate-using-webclient-and-taskasync-download-from-async-ctp作为参考。
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);
}
我预计文件的下载将从“Task.WhenAll(tasks)”点开始。但事实证明输出看起来像
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
为什么在调用 WaitAll 之前就开始下载?我可以改变什么来实现我想要的(即所有任务将同时开始)?
Thanks
为什么在调用 WaitAll 之前就开始下载?
首先,你没有打电话Task.WaitAll
,它同步阻塞,你正在调用Task.WhenAll
,它返回一个应该等待的可等待对象。
现在,正如其他人所说,当您调用异步方法时,即使不使用await
在它上面,它会触发异步操作,因为任何符合 TAP 的方法都会返回一个“热门任务”。
我可以改变什么来实现我想要的(即所有任务都会
同时开始)?
现在,如果您想推迟执行直到Task.WhenAll
, 您可以使用Enumerable.Select
将每个元素投影到Task
,并在将其传递给时将其具体化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");
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)