Cómo usar la barra de progreso durante la carga de un archivo xml

Quiero mostrar la barra de progreso durante la carga de un archivo XML remoto. Estoy utilizando el formulario de solicitud de Windows en Visual C # 2008 Express Edition.

private void button1_Click(object sender, EventArgs e) { string text = textBox1.Text; string url = "http://api.bing.net/xml.aspx?AppId=XXX&Query=" + text + "&Sources=Translation&Version=2.2&Market=en-us&Translation.SourceLanguage=en&Translation.TargetLanguage=De"; XmlDocument xml = new XmlDocument(); xml.Load(url); XmlNodeList node = xml.GetElementsByTagName("tra:TranslatedTerm"); for (int x = 0; x < node.Count; x++ ) { textBox2.Text = node[x].InnerText; progressbar1.Value = x; } } 

El código anterior no funciona para mostrar la carga de la barra de progreso. Por favor, sugiérame un código. Gracias por adelantado

¿Qué exactamente quieres reflejar en la barra de progreso? ¿Prefieres descargar el archivo (porque es grande) o procesarlo?

Barra de progreso que refleja el archivo de procesamiento

Su barra de progreso no cambia porque su método es sincrónico; no ocurrirá nada más, la unidad termina. BackgroundWorker clase BackgroundWorker está diseñada perfectamente para este tipo de problemas. Realiza el trabajo principal de forma asíncrona y puede informar que el progreso ha cambiado. Aquí es cómo cambiar el método de recorrido para usarlo:

 private void button1_Click(object sender, EventArgs e) { string text = textBox1.Text; string url = "http://api.bing.net/xml.aspx?AppId=XXX&Query=" + text + "&Sources=Translation&Version=2.2&Market=en-us&Translation.SourceLanguage=en&Translation.TargetLanguage=De"; XmlDocument xml = new XmlDocument(); xml.Load(url); XmlNodeList node = xml.GetElementsByTagName("tra:TranslatedTerm"); BackgroundWorker worker = new BackgroundWorker(); // tell the background worker it can report progress worker.WorkerReportsProgress = true; // add our event handlers worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.RunWorkerCompleted); worker.ProgressChanged += new ProgressChangedEventHandler(this.ProgressChanged); worker.DoWork += new DoWorkEventHandler(this.DoWork); // start the worker thread worker.RunWorkerAsync(node); } 

Ahora, la parte principal:

 private void DoWork(object sender, DoWorkEventArgs e) { // get a reference to the worker that started this request BackgroundWorker workerSender = sender as BackgroundWorker; // get a node list from agrument passed to RunWorkerAsync XmlNodeList node = e.Argument as XmlNodeList; for (int i = 0; x < node.Count; i++) { textBox2.Text = node[i].InnerText; workerSender.ReportProgress(node.Count / i); } } private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { // do something after work is completed } public void ProgressChanged( object sender, ProgressChangedEventArgs e ) { progressBar.Value = e.ProgressPercentage; } 

Barra de progreso que refleja la descarga de archivos

Intente usar HttpWebRequest para obtener el archivo como una secuencia.

 // Create a 'WebRequest' object with the specified url. WebRequest myWebRequest = WebRequest.Create(url); // Send the 'WebRequest' and wait for response. WebResponse myWebResponse = myWebRequest.GetResponse(); // Obtain a 'Stream' object associated with the response object. Stream myStream = myWebResponse.GetResponseStream(); long myStreamLenght = myWebResponse.ContentLength; 

Así que ya sabes la longitud de este archivo XML. Luego, debe leer el contenido de forma asíncrona ( BackgroundWorker and StreamReader es una buena idea). Use myStream.Position y myStreamLenght para calcular el progreso.

Sé que no soy muy específico, pero solo quería ponerte en la dirección correcta. Creo que no tiene sentido escribir sobre todas esas cosas aquí. Aquí tienes enlaces que te ayudarán a lidiar con Stream y BackgroundWorker :

El problema es que está utilizando un hilo de ventana, y la ventana no se puede volver a dibujar, hasta que finalice button1Click.

Use BackgroundWorker, puede informar el progreso llamando a backgroundworker.ReportProgress

La barra de progreso no funciona aquí, porque todo esto es un código “síncrono”. El evento Click bloquea la interfaz de usuario para que no se actualice.

Hay 2 soluciones.

Puede crear un hilo de fondo para procesar el archivo XML, y los informes de hilo de fondo avanzan al primer plano. Recomiendo usar un BackgroundWorker , pero hay mucho que aprender antes de hacer esto.

Una solución más fácil, aunque no óptima, es actualizar el formulario llamando a Application.DoEvents() después de cada actualización de progreso. Esto solo debe considerarse una solución a corto plazo, ya que si la tarea no es rápida, su aplicación podría aparecer como congelada.

Ambas soluciones tienen un inconveniente: cuando se actualiza su barra de progreso, su aplicación también procesará cualquier evento. Por lo tanto, debe deshabilitar manualmente su interfaz de usuario mientras la tarea se está procesando y volver a habilitarla cuando termine.

Hace un tiempo, creé una solución reutilizable para este problema. Creé un “ProgressDialog” que toma un delegado. El diálogo de progreso ejecuta el delegado, captura el progreso, actualiza su barra de progreso e incluso calcula el tiempo restante. La ventaja de usar el ProgressDialog es que puedo mostrar el diálogo en modo “modal”, que bloquea el acceso a la interfaz de usuario principal e incluso evita que el evento Click termine.
Desafortunadamente, no tengo ningún código para compartir, solo la idea.

En primer lugar, puede ser demasiado rápido para que lo veas. Intenta poner un Sleep dentro si estás probando eso, pero aún más, la razón por la que no se está actualizando es porque estás procesando y eso sucede en el mismo hilo que la interfaz de usuario principal esta usando.

Puede hacer que el progtwig procese todos los eventos llamando a Application.DoEvents (), pero al hacerlo, también reprocesará todo lo que el usuario haya hecho clic (incluido este botón), así que si desea DoEvents y asegúrese de no terminar procesando trabajo adicional, deshabilite el formulario cuando se inicie el método.

Dicho todo esto, un modelo mejor es enlazar su trabajo y actualizar la barra de progreso en un temporizador o una callback.