Чтобы обновить индикатор выполнения , пока ваш WebClient
загружает данные, вы должны использовать функцию, которая выполняет эту задачу в фоне .WebClient
имеет полезную функцию под названием DownloadFileAsync
.Эта функция делает именно это: загружает в фоновом режиме.
Код с таким изменением:
private void button4_Click(object sender, EventArgs e)
{
using (var client = new WebClient())
{
MessageBox.Show("File will start downloading");
var path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "SOMEFILENAME.exe");
client.DownloadFileAsync(new Uri("GOOGLE DRIVE LINK"), path);
MessageBox.Show("File has been downloaded!");
System.Diagnostics.Process.Start(path);
}
}
К сожалению, сейчас у нас проблема.Метод начинает загрузку в фоновом режиме, и ваш код немедленно продолжается.Это означает, что вы нажимаете свою кнопку, появляется первый MessageBox, второй MessageBox появляется сразу после первого, и если загрузка не завершена, когда вы закрываете второй, ваш файл выполняется слишком рано.
Чтобы избежать этого WebClient
имеет событий .Тот, который нам нужен, называется DownloadFileCompleted
.Как следует из названия, он выполняет все, что вы хотите, когда загрузка завершена.Итак, давайте посмотрим на новый код:
string path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "SOMEFILENAME.exe"); // We need our path to be global
private void button4_Click(object sender, EventArgs e)
{
using (var client = new WebClient())
{
client.DownloadFileCompleted += client_DownloadFileCompleted; // Add our new event handler
MessageBox.Show("File will start downloading");
client.DownloadFileAsync(new Uri("GOOGLE DRIVE LINK"), path);
}
}
private void client_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) // This is our new method!
{
MessageBox.Show("File has been downloaded!");
System.Diagnostics.Process.Start(path);
}
Наша следующая проблема: client
находится внутри блока using.Это отлично подходит для загрузок переднего плана, но если мы сделаем это асинхронно (это то, что мы делаем в фоновом режиме), ваш client
умрет, как только блок останется, то есть сразу после начала загрузки 1025 *.Итак, давайте сделаем наш client
глобальный, чтобы потом его можно было уничтожить.
string path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "SOMEFILENAME.exe");
WebClient client; // Here it is!
private void button4_Click(object sender, EventArgs e)
{
client = new WebClient(); // Create a new client here
client.DownloadFileCompleted += client_DownloadFileCompleted; // Add our new event handler
MessageBox.Show("File will start downloading");
client.DownloadFileAsync(new Uri("GOOGLE DRIVE LINK"), path);
}
private void client_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) // This is our new method!
{
MessageBox.Show("File has been downloaded!");
System.Diagnostics.Process.Start(path);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (client != null)
client.Dispose(); // We have to delete our client manually when we close the window or whenever you want
}
Теперь давайте предположим, что пользователь может нажать кнопку еще раз до завершения загрузки.Тогда наш клиент будет перезаписан, и загрузка будет отменена.Так что давайте просто проигнорируем нажатие кнопки, если мы уже что-то скачиваем, и создадим новый клиент, только если у нас его нет.Новый код:
string path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "SOMEFILENAME.exe");
WebClient client;
private void button4_Click(object sender, EventArgs e)
{
if (client != null && client.IsBusy) // If the client is already downloading something we don't start a new download
return;
if (client == null) // We only create a new client if we don't already have one
{
client = new WebClient(); // Create a new client here
client.DownloadFileCompleted += client_DownloadFileCompleted; // Add our new event handler
}
MessageBox.Show("File will start downloading");
client.DownloadFileAsync(new Uri("GOOGLE DRIVE LINK"), path);
}
private void client_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) // This is our new method!
{
MessageBox.Show("File has been downloaded!");
System.Diagnostics.Process.Start(path);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (client != null)
client.Dispose(); // We have to delete our client manually when we close the window or whenever you want
}
Теперь, когда скучная часть закончена, давайте перейдем к вашей проблеме: просмотр хода выполнения в индикаторе выполнения.WebClient
получил еще одно событие под названием DownloadProgressChanged
.Мы можем использовать его для обновления нашего индикатора выполнения.
Говоря о индикаторах выполнения: в Windows Forms вы можете создать его, выполнив поиск ProgressBar
в окне инструментов в Visual Studio.Тогда поместите это где-нибудь в своем окне.Компонент ProgressBar
имеет несколько свойств, которые важны для его диапазона.Нам повезло, значения по умолчанию - это именно то, что нам нужно.
Наш обновленный код (при условии, что ваш индикатор выполнения называется progressBar1
:
string path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "SOMEFILENAME.exe");
WebClient client;
private void button4_Click(object sender, EventArgs e)
{
if (client != null && client.IsBusy) // If the client is already downloading something we don't start a new download
return;
if (client == null) // We only create a new client if we don't already have one
{
client = new WebClient(); // Create a new client here
client.DownloadFileCompleted += client_DownloadFileCompleted;
client.DownloadProgressChanged += client_DownloadProgressChanged; // Add new event handler for updating the progress bar
}
MessageBox.Show("File will start downloading");
client.DownloadFileAsync(new Uri("GOOGLE DRIVE LINK"), path);
}
private void client_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) // This is our new method!
{
MessageBox.Show("File has been downloaded!");
System.Diagnostics.Process.Start(path);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (client != null)
client.Dispose(); // We have to delete our client manually when we close the window or whenever you want
}
private void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) // NEW
{
progressBar1.Value = e.ProgressPercentage;
}
Примечания:
- Вы можете создать метод
FormClosing
, дважды щелкнув событие FormClosing
в окне свойств вашего окна. - Вызов
client.Dispose()
необходим только в том случае, если ваша программа не закрывается после закрытия окна.В любом другом случае вы могли бы полностью избавиться от FormClosing
.
Вот и все, наконец. Надеюсь, это не слишком долго для вас, и я смогу вам помочь.для пояснения. Вот для чего здесь комментарии.