#c# #async-await #task
#c# #асинхронное ожидание #задача
Вопрос:
У меня есть приложение, написанное на C #. В этом приложении мне нужно загрузить несколько файлов. Как только все файлы будут загружены, мне нужно сделать что-то еще. Пытаясь загрузить файлы одновременно, я написал следующее:
private void DownloadFiles(string[] targets)
{
var tasks = new List<Task>();
foreach (var target in targets)
{
var task = DownloadFile(target);
tasks.Add(task);
}
Task.WaitAll(tasks.ToArray());
}
private async Task DownloadFile(string target)
{
using (var wc = new WebClient())
{
wc.DownloadProgressChanged = (object sender, DownloadProgressChangedEventArgs e) => {
Console.WriteLine(e.ProgressPercentage "% downloaded.");
}
wc.DownloadFileCompleted = (object sender, AsyncCompletedEventArgs e) => {
Console.WriteLine(target " was downloaded.");
// TODO: Signal this "Task" is done
}
await wc.DownloadFileTaskAsync(target, localPath);
}
}
Возможно, я запутался. На мой взгляд, я думаю, что мне нужно что-то сделать в DownloadFileCompleted
. Или, может быть, достаточно await wc.DownloadFileTaskAsync
строки.
Как мне загрузить несколько файлов одновременно, но дождаться, пока они все загрузятся, прежде чем продолжить?
Комментарии:
1. и что не так с вашим кодом?
2. @demo Я думаю, что его проблема в том, что он фактически не загружается параллельно (что он, очевидно, хочет сделать), потому что он ожидает
DownloadFileTaskAsync
вDownloadFile
методе
Ответ №1:
Вы могли бы сделать следующее:
private void DownloadFiles(string[] targets)
{
var tasks = new List<Task>();
using (var wc = new WebClient())
{
foreach (var target in targets)
{
var task = DownloadFile(wc, target);
tasks.Add(task);
}
Task.WaitAll(tasks.ToArray());
}
}
private Task DownloadFile(WebClient wc, string target)
{
wc.DownloadProgressChanged = (object sender, DownloadProgressChangedEventArgs e) =>
{
Console.WriteLine(e.ProgressPercentage "% downloaded.");
};
wc.DownloadFileCompleted = (object sender, AsyncCompletedEventArgs e) =>
{
Console.WriteLine(target " was downloaded.");
// TODO: Signal this "Task" is done
};
return wc.DownloadFileTaskAsync(target, localPath);
}
Я переместил WebClient в вызывающий метод, потому что вам придется держать его открытым до завершения всех загрузок (которые вы не знаете, когда они будут выполнены в вашем DownloadFile
методе).
Кроме того, я удалил async
из вашего объявления метода, потому что вам не нужно ждать чего-либо внутри метода.