2009-04-24 39 views
6

¿Cómo puedo forzar la ejecución de una sección de código en mi hilo principal?Forzar la ejecución del código en el hilo principal

Esto es por eso que me gustaría saber:

Tengo un cuadro de mensaje personalizado creado que a veces consigue muestra de un hilo que no es el hilo principal. Sin embargo, cuando se llama al constructor del cuadro de mensaje obtengo una InvalidOperationException que dice "El hilo que llama debe ser STA, porque muchos componentes de UI lo requieren". Esto tiene sentido, los elementos de la IU deben manejarse en el hilo principal.

Mi función MessageBox.ShowMessage (...) es una función estática que crea una instancia de mi cuadro de mensaje personalizado y lo muestra. ¿Hay algo que pueda poner en ShowMessage que fuerce la creación del cuadro de mensaje y se muestre en el hilo principal? En otra parte de mi código utilizo Control.BeginInvoke para manejar problemas similares, pero dado que es una función estática, no hay un elemento de interfaz de usuario ya existente para invocar a BeginInvoke.

¿Debo llamar a MessageBox.ShowMessage desde con Control.BeginInvoke? Prefiero que se llame a BeginInvoke (o a un equivalente) desde ShowMessage.

Respuesta

5

Hay algunas opciones aquí:

  • hacer la segunda STA hilo (sólo se puede hacer esto por su propio Thread - no para ThreadPool hilos) - a través de .SetApartmentState(ApartmentState.STA);
  • ver si SynchronizationContext.Current es no- nulo; si es así, utilizar Send/Post
  • pasar a la forma/de control en una instancia como ISynchronizeInvoke (no puede aplicarse a WPF - No estoy seguro al 100%)
+0

¿Tiene un enlace que explica cómo implementar la primera opción que enumera? – w4g3n3r

+0

Llame a Thread.SetApartmentState() antes de iniciar el hilo. – itowlson

+0

Al crear el hilo, simplemente llame a .SetApartmentState como se muestra en la respuesta (editada). Avíseme si necesita más ayuda para crear el hilo en primer lugar. –

5

Su pensamiento es correcto - con el fin de para que funcione correctamente, tendrá que recibir una llamada desde el hilo principal.

¿La manera más simple? Cuando inicie su formulario principal, guarde una referencia en una variable estática que sea visible para su llamada a ShowMessage(). Entonces, su ShowMessage puede hacer la norma:

if(myForm.InvokeRequired) 
{ 
    myForm.Invoke(() => ShowMessage(arg1,arg2,arg3)); 
    return; 
} 
.... other code here.... 
+3

Es probable que no necesite una variable explícita: en WPF podría usar Application.Current.MainWindow, en WinForms una ventana de la colección Application.OpenForms. – itowlson

1

En lugar de mostrar directamente el cuadro de mensaje, basta con enviar un mensaje a su hilo principal, lo que indica que el hilo principal para mostrar un cuadro de mensaje.

+0

+1 esto es en realidad mucho menos intrusivo IMO – Rick

+0

¿Puede darnos un ejemplo de cómo hacer esto? – Brabbeldas

Cuestiones relacionadas