Подтвердить что ты не робот

Загрузка асинхронного файла с помощью панели выполнения

Я пытаюсь изменить ход хода выполнения, так как изменяется скорость загрузки WebClient. Этот код по-прежнему загружает файл, но когда я вызываю startDownload(), окно зависает при загрузке файла. Я хотел бы, чтобы пользователь мог видеть изменение хода работы при загрузке заставки. Есть ли способ исправить это, чтобы пользователь мог увидеть прогресс progressBar2 изменить?

private void startDownload()
{
    WebClient client = new WebClient();
    client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
    client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
    client.DownloadFileAsync(new Uri("http://joshua-ferrara.com/luahelper/lua.syn"), @"C:\LUAHelper\Syntax Files\lua.syn");
}
void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    double bytesIn = double.Parse(e.BytesReceived.ToString());
    double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
    double percentage = bytesIn / totalBytes * 100;
    label2.Text = "Downloaded " + e.BytesReceived + " of " + e.TotalBytesToReceive;
    progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
}
void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
    label2.Text = "Completed";
}
4b9b3361

Ответ 1

Вы должны вызвать startDownload() из потока пользовательского интерфейса. Вся идея WebClient.DownloadFileAsync() заключается в том, что она автоматически создаст рабочий поток, не блокируя вызывающий поток. В startDownload() вы указали обратные вызовы, которые изменяют элементы управления, которые, как я полагаю, были созданы потоком пользовательского интерфейса. Таким образом, если вы вызываете startDownload() из фонового потока, это вызовет проблемы, потому что поток может изменять только созданные элементы пользовательского интерфейса.

Как он должен работать, вы вызываете startDownload() из потока пользовательского интерфейса, startDownload(), как вы определили, он устанавливает обратные вызовы вызовов, которые обрабатываются потоком пользовательского интерфейса. Затем он запускается асинхронно и возвращается немедленно. Поток пользовательского интерфейса будет уведомлен о том, что изменения прогресса и код, ответственный за обновление контроля выполнения, будут выполняться в потоке пользовательского интерфейса, и не должно быть никаких проблем.

Ответ 2

Пользовательский интерфейс будет заморожен, когда вы нажмете startDownload(). Если вы не хотите, чтобы форма формы зависала, вы используете startDownload() в другом потоке и обновляете прогресс в кросс-threaded. Один из способов,

private void startDownload()
{
    Thread thread = new Thread(() => {
          WebClient client = new WebClient();
          client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
          client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
          client.DownloadFileAsync(new Uri("http://joshua-ferrara.com/luahelper/lua.syn"), @"C:\LUAHelper\Syntax Files\lua.syn");
    });
    thread.Start();
}
void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    this.BeginInvoke((MethodInvoker) delegate {
        double bytesIn = double.Parse(e.BytesReceived.ToString());
        double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
        double percentage = bytesIn / totalBytes * 100;
        label2.Text = "Downloaded " + e.BytesReceived + " of " + e.TotalBytesToReceive;
        progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
    });
}
void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
    this.BeginInvoke((MethodInvoker) delegate {
         label2.Text = "Completed";
    }); 
}

Читайте больше многопоточности в Google, как это http://msdn.microsoft.com/en-us/library/ms951089.aspx

- Исправлено пропущенное закрытие); к объявлению bgThread

Ответ 3

Я считаю, что эта статья приведет вас в правильном направлении http://www.dreamincode.net/forums/topic/115491-download-file-asynchronously-with-progressbar/.

И в этой статье MSDN http://msdn.microsoft.com/en-us/library/ms229675.aspx обсуждается, как "Файл загружается в рабочий поток компонента BackgroundWorker, который запускает обработчик событий DoWork Этот поток начинается, когда ваш код вызывает метод RunWorkerAsync."