2010-02-02 13 views
5

Estoy utilizando 5 objetos BackgroundWorker que se ejecutan al mismo tiempo para un propósito determinado, y todos ellos tienen que cambiar la misma etiqueta. ¿Cómo puedo hacer eso?BackgroundWorker acceso multiproceso al formulario

¿Cómo modifico el formulario de más de un hilo, entonces? ¿Y cómo lo hago en caso de que quiera cambiar una cadena pública?

Respuesta

17

Use Control.Invoke con un delegado.

En el subproceso de trabajo de fondo, en lugar de decir

label4.Text = "Hello"; 

dicen

label4.Invoke(new Action(() => 
{ 
    label4.Text = "Hello"; 
} 
)); 

Todo dentro de la {} ejecuta en el subproceso del control, por lo que evitar la excepción.

Esto le permite realizar cambios arbitrarios en su interfaz de usuario desde un BackgroundWorker en lugar de solo informar el progreso.

+0

ReportProgress también le permitirá realizar cambios arbitrarios en la interfaz de usuario. –

+0

¿cómo lo invoco si ahora está pasando a una cadena pública de mi formulario? – Marcelo

+0

@Henk: ReportProgress solo permitirá que BackroundWorker envíe un único objeto "UserState", que luego deberá ser interpretado por el controlador de eventos ProgressChanged para actualizar realmente la UI. Lo que estaba tratando de decir es que con el enfoque Invoke() puede poner el código para la actualización dentro del método donde crea el BackgroundWorker, lo que lleva a un código más eficiente y más legible. Esta es una decisión de diseño, por supuesto, con todos los intercambios normales. – RobC

2

Puede usar el método ReportProgress en su BackgroundWorker donde desea que la etiqueta cambie y escriba el código real en el controlador de eventos ProgressChanged.

+0

el problema es que esta es una excepción que muestra la etiqueta, por lo que no siempre que el método ejecutado por backgroundworker hará ninguna interacción con el formulario – Marcelo

+0

Puede usar la sugerencia de RaYell para publicar información en la GUI que puede hacer la actualización. –

0

Eche un vistazo a this answer. No importa si tiene uno, cinco o mil hilos de trabajo (en el sentido del concepto).

1

Debería tener mucho cuidado de llamar a la invocación sincrónica en lugar de a la invocación asincrónica de BeginInvoke en una interfaz gráfica de usuario. Pronto tendrá una interfaz gráfica de usuario insensible y descuidada que parece estar luchando por pintarse a sí misma, así como el potencial de bloqueos.
Depende de la frecuencia con la que lo actualice, ¿y su hilo de fondo realmente necesita esperar a que la interfaz haya retornado? Eso suena como un problema con tu modelo.

1

Además de Control.BeginInvoke, puede echar un vistazo a SynchronizationContext.

Cuando está creando BackgroundWorkers, suponiendo que los está creando desde el subproceso UI, transfiere SynchronizationContext.Current a los trabajadores. Cuando los BackgroundWorkers están listos para invocar algo en el hilo de la interfaz de usuario, llaman al método Synchronization.Post en la instancia de SynchronizationContext pasada cuando se crearon.

Hay dos buenos artículos en SynchronizationContext here y here.