2009-08-15 3 views
6

Recientemente, encontré esta situación en la que quería mostrar un formulario en otro hilo (no el hilo principal/IU). Usé un hilo de subprocesos. El formulario alojaba un RCW (para un componente COM). La instanciación del formulario me dio la excepción de que el hilo debe ser una STA. Traté de establecer el estado del departamento como STA. Pero eso tampoco funcionó. Finalmente terminé creando un hilo de manera explícita y eso funcionó (utilicé ShowDialog y no necesito crear una bomba de meesage).¿Por qué no podemos cambiar el estado de un subproceso de ThreadPool y por qué no necesitamos una bomba de mensajes cuando se usa ShowDialog?

EDIT:

  • Sé que threadpool hilos son MTA. Pero, ¿por qué no se puede establecer en STA? Solo curiosidad por esto.
  • Otra pregunta que acaba de hacer estallar en mi cabeza: ¿Por qué no requiere una bomba
    mensaje cuando ShowDialog() (a
    pantalla un formulario) se utiliza

Respuesta

8

El apartamento se selecciona mediante una llamada a CoInitializeEx(). Un hilo en el grupo de subprocesos ya ha hecho esa llamada, cambiando el apartamento después de que la llamada no sea posible.

El hecho de que un grupo de subprocesos elija MTA tiene sentido, después de todo es una cadena de trabajo y no debe ser bloqueada por llamadas a métodos que se deben calcular. La selección de un apartamento de subproceso único tiene el requisito adicional de bombear un bucle de mensaje. Algo que nunca esperarías que hiciera un subproceso de subprocesamiento.

El bucle de mensajes es necesario porque ese es el vehículo que COM utiliza para coordinar una llamada realizada en otro hilo. Esa llamada debe ser "inyectada" en el hilo STA, eso solo es posible si el hilo se encuentra en un estado de reposo conocido. Si no es así, tal llamada causaría problemas importantes de reentrada. Lo cual a veces sucede incluso si el hilo está bombeando el ciclo.

No necesitó bombear un bucle de mensaje usted mismo con Application.Run() porque ShowDialog() inicia su propio bucle de mensaje. Así es como gana la modalidad. Ese bucle anidado sale tan pronto como se cierra el cuadro de diálogo.

+0

Gracias por la respuesta. ¿Puede señalar un enlace que dice que ShowDialog() inicia su propio bucle de mensajes. –

+0

http://www.red-gate.com/products/reflector. Recomendado. –

+0

Gracias. Application.RunDialog (esto) hace el truco. –

8

Usted no debe confiar en comportamiento específico para subprocesos de grupo de subprocesos. En general, un subproceso en el grupo de subprocesos debería poder ser reemplazado en cualquier momento por el CLR, sin su conocimiento. Los subprocesos del grupo de subprocesos están destinados a ser utilizados con tareas simples, preferiblemente de corta vida.

Si desea tener un control detallado de la configuración de subprocesos, debe crear un subproceso dedicado. Configurar el estado del departamento es un ejemplo perfecto de esto.


Además de los motivos teóricos anteriores, hay un problema práctico con lo que está intentando. Hospedar un formulario en un segundo subproceso no funciona (sin mucho trabajo adicional). Los formularios se deben ejecutar en el mismo hilo que la bomba de mensajes; de lo contrario, no recibirán ningún mensaje de Windows y no se actualizarán correctamente.

Puede crear un formulario en un subproceso separado si implementa una bomba de mensajes completa para ese subproceso, pero generalmente es una mejor idea simplemente poner sus elementos de trabajo en subprocesos de fondo y utilizar técnicas de programación asíncronas para mantener su UI hilo receptivo

+0

Gracias por la respuesta. "Un hilo en el grupo de hilos debería poder ser reemplazado en cualquier momento por el CLR, sin su conocimiento." No sabia esto ¿Qué significa exactamente? –

+1

El grupo de subprocesos crea y destruye subprocesos a medida que se ejecuta su programa. No hay (necesariamente) solo un número fijo de subprocesos en el grupo de subprocesos. .NET thread es aún más flexible en este sentido. Tiene todo tipo de nuevas herramientas para robar trabajo, etc., que hacen que genere y destruya hilos durante el tiempo de ejecución de su aplicación. –

+0

oh..si soy totalmente consciente de la bomba de mensajes. Por lo tanto, crear un formulario a través de subproceso de subprocesamiento o un subproceso nuevo requerirá que se adjunte una bomba de mensaje a dicho subproceso. Pero, utilizo ShowDialog() para mostrar el formulario y que no requiere bomba de mensajes, ya que es una llamada de bloqueo. En realidad, tenía curiosidad sobre por qué no podemos cambiar el estado del apartamento de un hilo de ThreadPool para que sea STA. Gracias. –

Cuestiones relacionadas