C# асинхронная загрузка файла

90
28 сентября 2021, 20:10

Целиком задача заключается в загрузке трех картинок для трех PictureBox. По условию задачи пользователь может загружать их в любой момент, поэтому я считаю, что загрузки должны выполняться асинхронно.
Сейчас я выполняю подзадачу по загрузке лишь одной картинки, и поэтому пишу следующий код:

async void DownloadFile(string link, string filename)
    {         
        await wc.DownloadFileTaskAsync(new Uri(link), filename);
    }
    private void PB1Download_Click(object sender, EventArgs e)
    {
        string filename = Directory.GetCurrentDirectory() + "\\image " + downloadsCount.ToString() + ".jpg";
        string link = TB1Link.Text;
        Task.Run(() => DownloadFile(link, filename)).Wait();
        PB1.Image = new Bitmap(filename);
    }

Выполнение этого кода выбрасывает исключение:

Насколько я понял, это связано с тем, что загрузка Bitmap'а в PictireBox выполняется РАНЬШЕ, чем картинка скачалась, ибо задача асинхронна. Но при этом я думал, что метод Wait поможет дождаться окончания выполнения задачи и все-таки картинка будет успешно загружена в PictureBox. Что я понимаю и делаю не так?

Answer 1

Попробуйте вот так

async Task DownloadFile(string link, string filename)
{         
    await wc.DownloadFileTaskAsync(new Uri(link), filename);
}
private async void PB1Download_Click(object sender, EventArgs e)
{
    string filename = Path.Combine(Directory.GetCurrentDirectory(), $"image{downloadsCount}.jpg");
    string link = TB1Link.Text;
    await DownloadFile(link, filename);
    PB1.Image = new Bitmap(filename);
}
Answer 2

Верный ответ уже дан, но мне есть что сказать.

Самый простой способ загрузки изображения в PictureBox - использовате его собственные возможности. В частности, метод PictureBox.LoadAsync.

Однако, вам нужно ещё и сохранить файл локально. Поэтому этот способ в данном случае не подоходит.

В этом методе применение async/await избыточно:

async Task DownloadFile(string link, string filename)
{         
    await wc.DownloadFileTaskAsync(new Uri(link), filename);
}

Task сам по себе является awaitable объектом, поэтому код можно переписать так:

Task DownloadFile(string link, string filename)
{
    return wc.DownloadFileTaskAsync(new Uri(link), filename);
}

Вызов метода в обоих случаях одинаков:

await DownloadFile("...", "...");

Для нахождения и устранения таких ошибок можно использовать, например, AsyncFixer.

Вы хотите загружать одновременно несколько картинок. Судя по названию и по сигнатуре метода, wc - это WebClient. Но этот класс не является потокобезопасным. Поэтому нужно либо для каждой загрузки создавать своей экземпляр WebClient, либо использовать HttpClient - его экземпляр можно использовать для нескольких загрузок одновременно.

READ ALSO
C# перенос кода в функцию [закрыт]

C# перенос кода в функцию [закрыт]

Хотите улучшить этот вопрос? Добавьте больше подробностей и уточните проблему, отредактировав это сообщение

299
Незапускается поиск Bluetooth устройств

Незапускается поиск Bluetooth устройств

Пишу кроссплатформенную реализацию поиска BLE устройствИмею следующий код обертки над стандартным UWP классом:

150
Зачем LinkerPleaseInclude

Зачем LinkerPleaseInclude

Делал кастомный UITextView и сталкнулся с проблемой при байндинге текстового поля прога просто вылетала

244