使用进度条下载异步文件

随着WebClient下载进度的变化,我试图让进度条的进度发生变化。 这个代码仍然下载文件,当我调用startDownload() ,窗口会在下载文件时冻结。 我希望用户能够在启动屏幕加载时看到进度更改。 有没有办法解决这个问题,以便用户可以看到progressBar2的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"; } 

您应该从UI线程调用startDownload()WebClient.DownloadFileAsync()的整个想法是它将自动为您生成一个工作线程,而不会阻塞调用线程。 在startDownload() ,您指定了修改我认为是由UI线程创建的控件的回调。 因此,如果从后台线程调用startDownload() ,则会导致问题,因为线程只能修改它创建的UI元素。

它应该工作的方式是你从UI线程调用startDownload()startDownload()因为你定义它设置由UI线程处理的事件回调。 然后它以异步方式开始下载并立即返回。 当进度发生变化时,将通知UI线程,并且负责更新进度条控件的代码将在UI线程上执行,并且应该没有任何问题。

单击startDownload()时,UI线程将被冻结。 如果您不希望get form冻结,可以在另一个线程中使用startDownload()并在交叉线程中进行更新。 单程,

 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中阅读更多multithreading,如下所示http://msdn.microsoft.com/en-us/library/ms951089.aspx

– 修复失踪关闭); 到bgThread声明

我相信这篇文章将引导您走向正确的方向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方法。“

  public class ProgressEventArgsEx { public int Percentage { get; set; } public string Text { get; set; } } public async static Task DownloadStraingAsyncronous(string url, IProgress progress) { WebClient c = new WebClient(); byte[] buffer = new byte[1024]; var bytes = 0; var all = String.Empty; using (var stream = await c.OpenReadTaskAsync(url)) { int total = -1; Int32.TryParse(c.ResponseHeaders[HttpRequestHeader.ContentLength], out total); for (; ; ) { int len = await stream.ReadAsync(buffer, 0, buffer.Length); if (len == 0) break; string text = c.Encoding.GetString(buffer, 0, len); bytes += len; all += text; if (progress != null) { var args = new ProgressEventArgsEx(); args.Percentage = (total <= 0 ? 0 : (100 * bytes) / total); progress.Report(args); } } } return all; } // Sample private async void Bttn_Click(object sender, RoutedEventArgs e) { //construct Progress, passing ReportProgress as the Action var progressIndicator = new Progress(ReportProgress); await TaskLoader.DownloadStraingAsyncronous(tbx.Text, progressIndicator); } private void ReportProgress(ProgressEventArgsEx args) { this.statusText.Text = args.Text + " " + args.Percentage; }