2012-02-27 28 views
14

Estoy intentando que el progreso de una barra de progreso cambie a medida que el progreso de descarga WebClient cambia. Este código aún descarga el archivo aún cuando llamo al startDownload() y la ventana se congela mientras descarga el archivo. Me gustaría que el usuario pueda ver el cambio de progreso a medida que se carga la pantalla de bienvenida. ¿Hay alguna manera de solucionar esto para que el usuario pueda ver el progreso del cambio progressBar2?Descarga asíncrona de archivos con barra de progreso

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"; 
} 
+0

si la ventana se bloquea significa que la persona está descargando en el subproceso de la interfaz de usuario que se traduce en que su código es síncrono y no asíncrono. – Joakim

+0

Estoy llamando 'startDownload()' a través de un trabajador en segundo plano que se ejecuta de forma asíncrona. Eso no debería causar que la ventana se congele, ¿verdad? –

+6

No coloque un prefijo en sus títulos con "C#" y tal. Para eso son las etiquetas. –

Respuesta

9

Debe llamar al startDownload() desde el hilo de la interfaz de usuario. La idea completa de WebClient.DownloadFileAsync() es generar un hilo de trabajo automáticamente sin bloquear el hilo de llamada. En startDownload(), especificó devoluciones de llamada que modifican los controles que supongo fueron creados por el subproceso de la interfaz de usuario. Por lo tanto, si llama al startDownload() desde un hilo de fondo, causará problemas, porque un hilo solo puede modificar los elementos de la IU que creó.

La manera en que se supone que funciona es si llama al startDownload() desde el hilo de la interfaz de usuario, startDownload(), como definió, configura las llamadas a eventos que maneja el hilo de la interfaz de usuario. A continuación, inicia la descarga de forma asincrónica y regresa inmediatamente. El subproceso de interfaz de usuario será notificado cuando el progreso cambie y el código responsable de actualizar el control de barra de progreso se ejecutará en el subproceso de interfaz de usuario, y no debería haber ningún problema.

+0

Gracias, no me di cuenta de que no podría iniciar la descarga a través de otro hilo asincrónico. Todo esta funcionando bien ahora. –

1

Creo que este artículo lo guiará en la dirección correcta http://www.dreamincode.net/forums/topic/115491-download-file-asynchronously-with-progressbar/.

Y en este artículo de MSDN http://msdn.microsoft.com/en-us/library/ms229675.aspx analiza cómo "El archivo se descarga en el subproceso de trabajo del componente BackgroundWorker, que se ejecuta el controlador de eventos DoWork. Este hilo se inicia cuando el código llama al método RunWorkerAsync."

+0

Ya he seguido ese artículo que generó el mismo problema. –

+2

¿Está utilizando su función para mostrar el progreso de la descarga desde el hilo de fondo? Si es así, debe iniciarlo en el hilo de UI, pero enganche la función de progreso del trabajador de fondo. Espero que pueda ser de alguna ayuda. Todavía estoy leyendo un poco sobre el problema que tienes, así que espero poder encontrar otra solución. – SMT

18

UI El hilo se congelará al hacer clic en iniciarDescargar(). Si no desea que se congele el formulario, use startDownload() en otro hilo y realice la actualización del progreso en el subproceso cruzado. Una forma ,

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"; 
    }); 
} 

Leer más multi-threading en Google como esto http://msdn.microsoft.com/en-us/library/ms951089.aspx

-Fixed falta cerrar); a la declaración de bgThread

+0

MethodInvoker no viene en mi programa, ¿qué debo hacer? –

+1

BeginInvoke está en el espacio de nombres de WinForms. Si está utilizando WPF, debe usar Dispatcher.BeginInvoke – Tsukasa

+0

Usando el código anterior para descargar los archivos, pero no puedo conectar el error del servidor remoto. –