Я пытаюсь загрузить файл, дождитесь окончания загрузки файла, а затем прочитайте файл после этого. У меня есть следующие методы:
private async Task startDownload(string link, string savePath)
{
WebClient client = new WebClient();
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
await client.DownloadFileTaskAsync(new Uri(link), savePath);
}
private void checkUpdateButton_Click(object sender, EventArgs e)
{
Task task = Task.Factory.StartNew(() => startDownload(versionLink, versionSaveTo));
task.Wait();
if (task.IsCompleted)
{
checkVersion();
}
}
Метод checkVersion()
считывает загруженный файл. Это бросает IOException
говоря, что файл используется кем-то другим и не может быть прочитан. Я думал, что с task.Wait
будет препятствовать выполнению остальной части метода до завершения задачи?
Task.Wait
заблокирует текущий поток (в данном случае поток пользовательского интерфейса) и дождитесь завершения задачи. В этом случае задача завершается с ошибкой, поэтому Task.Wait
будет Task.Wait
эту ошибку, заключенную в Task.Wait
AggregateException
.
Как отмечали другие, вы должны использовать await
вместо Wait
. Кроме того, DownloadFileCompleted
не имеет смысла, поскольку вы используете DownloadFileTaskAsync
(а не DownloadFileAsync
); и StartNew
так как загрузка является асинхронной.
О, и пусть утилита WebClient
и убедитесь, что наше соглашение об именах следует Асинхронному шаблону на основе задач.
private async Task startDownloadAsync(string link, string savePath)
{
using (var client = new WebClient())
{
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
await client.DownloadFileTaskAsync(new Uri(link), savePath);
}
}
private async void checkUpdateButton_Click(object sender, EventArgs e)
{
await startDownloadAsync(versionLink, versionSaveTo);
checkVersion();
}
Функция startDownload уже асинхронна, поэтому она начнет задачу и сразу вернется. Вы можете использовать ContinueWith для обеспечения выполнения задачи перед вызовом функции checkVersion().
private void checkUpdateButton_Click(object sender, EventArgs e)
{
var task = startDownload(versionLink, versionSaveTo);
task.ContinueWith((x) => checkVersion());
}
Альтернатива, как указывает Servy, заключается в использовании async/wait в событии Click.
private async void checkUpdateButton_Click(object sender, EventArgs e)
{
await startDownload(versionLink, versionSaveTo);
checkVersion();
}
Вам нужно будет дождаться Task.Factory.StartNew(...)
, таким образом, он не блокирует поток пользовательского интерфейса.
private async void button1_Click(object sender, EventArgs e)
{
Task task = await Task.Factory.StartNew(() => startDownload("http://www.zwaldtransport.com/images/placeholders/placeholder1.jpg", "" + "sd.jpg"));
}
private async Task startDownload(string link, string savePath)
{
WebClient client = new WebClient();
client.DownloadProgressChanged += Client_DownloadProgressChanged;
client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
await client.DownloadFileTaskAsync(new Uri(link), savePath);
}
private void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
checkVersion();
Console.WriteLine("Done, unless error or cancelled.");
}
private void Client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
Console.WriteLine("Progress changed.");
}
Image placeholder courtesy Google Images и другой сайт.
checkVersion()
в событие DownloadFileCompleted, если этого хочет OP. Должно быть, я неправильно понял.
StartDownload
, вы должны просто вернутьclient.DownloadFileTaskAsync(new Uri(link), savePath);
Wait
выполнения задачи в потоке пользовательского интерфейса. Вы должныawait
этого вместо этого.