¿Cómo puedo Producir para el subproceso de interfaz de usuario para la actualización de la interfaz de usuario mientras se hace el procesamiento por lotes en un WinForm app?

StackOverflow https://stackoverflow.com/questions/106036

  •  01-07-2019
  •  | 
  •  

Pregunta

Tengo un WinForms aplicación escrita en C# con .NET 3.5.Se ejecuta un largo proceso por lotes.Quiero la app para actualizar el estado de lo que el proceso por lotes está haciendo.¿Cuál es la mejor manera de actualizar la interfaz de usuario?

¿Fue útil?

Solución

El BackgroundWorker suena como el objeto que desea.

Otros consejos

De forma rápida y sucia es el uso de Application.DoEvents() Pero esto puede causar problemas con el orden de los eventos se manejan.Así que no es recomendable

El problema es, probablemente, no se que tienen que ceder para el subproceso de interfaz de usuario, sino que el procesamiento en el subproceso de interfaz de usuario bloqueo de mensajes de control.Puede utilizar el componente backgroundworker para hacer el procesamiento por lotes en un subproceso diferente sin bloquear el subproceso de interfaz de usuario.

Ejecutar el proceso largo en un subproceso en segundo plano.El fondo de la clase trabajadora es una manera fácil de hacer esto - proporciona soporte para el envío de actualizaciones de progreso y la finalización de los eventos para que los controladores de eventos son llamados en el hilo correcto para usted.Esto mantiene el código limpio y conciso.

Para mostrar las actualizaciones, las barras de progreso o texto de barra de estado son dos de los enfoques más comunes.

La cosa clave a recordar es que si usted está haciendo las cosas en un subproceso en segundo plano, debe cambiar para el subproceso de interfaz de usuario para la actualización de controles de windows, etc.

A la carne lo que la gente está diciendo acerca de DoEvents, he aquí una descripción de lo que puede suceder.

Dicen que usted tiene algunos formulario con los datos en él y su tiempo de eventos que se ejecutan es guardarlo en la base de datos o a la generación de un informe basado en él.Comience a ahorrar o generar el informe y, a continuación, periódicamente se llame DoEvents para que la pantalla se pone en la pintura.

Por desgracia, la pantalla no es sólo la pintura, que también va a reaccionar a las acciones del usuario.Esto es debido a que DoEvents deja lo que estás haciendo ahora para procesar todos los mensajes de windows a la espera de ser procesado por su aplicación Winforms.Estos mensajes incluyen solicitudes para volver a dibujar, así como cualquier usuario de escribir, clic, etc.

Así, por ejemplo, mientras que usted está guardando los datos, el usuario puede hacer cosas como hacer la aplicación mostrará un cuadro de diálogo modal que es completamente ajena a la larga tarea que se esté ejecutando (por ejemplo, Ayuda->Acerca de).Ahora estás reaccionando a las nuevas acciones del usuario dentro de la ejecución ya larga tarea en ejecución.DoEvents volverá cuando todos los eventos que estaban esperando cuando usted llamó terminado, y luego de su larga tarea en ejecución continuará.

Lo que si el usuario no cierre el cuadro de diálogo modal?Su larga tarea en ejecución espera indefinidamente hasta que este cuadro de diálogo se cierra.Si usted está cometiendo a una base de datos y la celebración de una transacción, ahora que usted está sosteniendo una transacción abierta mientras el usuario está tomando un café.Ya sea que tu transacción se agota y pierde su persistencia en el trabajo, o la transacción no se agota el tiempo y que potencialmente interbloqueo de otros usuarios de la DB.

Lo que ocurre aquí es que la Aplicación.DoEvents hace que su código reentrante.Ver la definición de wikipedia aquí.Nota de algunos puntos de la parte superior del artículo, que para el código reentrante, es:

  • Debe tener ninguna estática (o global) no constante de datos.
  • Debe trabajar sólo en los datos proporcionados por el autor de la llamada.
  • No debe depender de los bloqueos a singleton recursos.
  • No debe llamar a no reentrante de programas de ordenador o rutinas.

Es muy poco probable que larga la ejecución de código en una aplicación WinForms está trabajando únicamente en los datos que se pasan al método por el que llama, no estática de datos, no tiene bloqueos, y sólo las llamadas a otros métodos reentrantes.

Como mucha gente de aquí están diciendo, DoEvents puede llevar a algunos muy extraños escenarios en el código.Los errores que puede llevar a que puede ser muy difícil de diagnosticar, y el usuario no es probable que te dicen: "Oh, esto podría haber sucedido porque me hizo clic en este relacionado botón mientras yo estaba esperando que ahorrar".

Utilice el componente backgroundworker para ejecutar su procesamiento por lotes en un hilo separado, esto no los tendrá impacto en el subproceso de interfaz de usuario.

Quiero repetir lo que mis anteriores comentaristas señalaron:por favor, evite DoEvents() siempre que sea posible, ya que esto es casi siempre una forma de "hackear" y hace que el mantenimiento de las pesadillas.

Si van a la BackgroundWorker carretera (sugiero), tendrá que lidiar con la cruz-threading llamadas a la interfaz de usuario si desea llamar a los métodos o propiedades de los Controles, ya que estos son el hilo-afín y debe ser llamado sólo desde el hilo que fueron creados.El Control Del Uso.Invoke() y/o de Control.BeginInvoke() según corresponda.

Si está ejecutando en un segundo plano/subproceso de trabajo, puede llamar a Control.Invoke en uno de sus controles de interfaz de usuario para ejecutar un delegado en el subproceso de interfaz de usuario.

Control.Invoke es sincrónico (Espera hasta que el delegado de los retornos).Si usted no quiere esperar para que usted use .BeginInvoke() a la cola en el comando.

El returnvalue .BeginInvoke() permite comprobar si el método de completado o esperar hasta que se complete.

Uso Backgroundworker, y si usted también está tratando de actualizar la interfaz gráfica de usuario hilo por el manejo de la ProgressChanged evento(como, por un ProgressBar), asegúrate de establecer WorkerReportsProgress=true, o el hilo que está reportando el progreso va a morir la primera vez que se intenta llamar ReportProgress...

se produce una excepción, pero es posible que no vea a menos que se tiene cuando se lanza " activado, y la salida se acaba de mostrar que el hilo salido.

Aplicación.DoEvents() o posiblemente ejecutar el lote en un subproceso independiente?

DoEvents() era lo que yo estaba buscando, pero también he votado hasta el backgroundworker respuestas, ya que parece una buena solución que voy a investigar un poco más.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top