2008-10-03 22 views
97

Del artículo de MSDN en STAThread:STAThread y multithreading

Indica que el modelo de subprocesos COM de una aplicación es el apartamento de un único subproceso (STA).

(Como referencia, eso es the entire article.)

de un solo subproceso apartamento ... OK, que se fue por encima de mi cabeza. Además, leí en alguna parte que a menos que tu aplicación use interoperabilidad COM, este atributo en realidad no hace nada en absoluto. Entonces, ¿qué es exactamente lo que hace, y cómo afecta esto a las aplicaciones multiproceso? ¿Deben las aplicaciones multiproceso (que incluye cualquier cosa desde cualquier persona que usa Timer s a llamadas a métodos asíncronos, no solo grupos de subprocesos y similares) usar MTAThread, incluso si es 'solo para estar seguro'? ¿Qué hace STAThread y MTAThread en realidad?

Respuesta

58

Apartment threading es un concepto COM; si no está utilizando COM, y ninguna de las API a las que llama utiliza COM "debajo de las sábanas", entonces no necesita preocuparse por los apartamentos.

Si necesita estar al tanto de los apartamentos, entonces los detalles pueden obtener a little complicated; una versión probablemente demasiado simplificada es que los objetos COM etiquetados como STA se deben ejecutar en un STAThread, y los objetos COM marcados MTA se deben ejecutar en un hilo MTA. Al usar estas reglas, COM puede optimizar las llamadas entre estos diferentes objetos, evitando las referencias donde no es necesario.

+7

Eso está demasiado simplificado. Los objetos multiproceso se pueden ejecutar en cualquier hilo. Los objetos con subprocesos solo se pueden ejecutar en el departamento en el que se crearon. –

+27

Una llamada desde un objeto STA en un hilo STA a un objeto MTA se convertirá en un hilo MTA (a menos que el objeto MTA implemente el marcador general) . Como dije, los detalles pueden complicarse. (Trabajé en el equipo COM durante varios años * sonrisa *) – Bruce

+9

Algunas veces debe tener esto en cuenta incluso si no está utilizando COM directamente. Un subproceso debe utilizar el modelo de Apartamento de subproceso único si muestra ventanas gráficas. Esta es la razón por la cual [STAThread] siempre se muestra en la parte superior del método principal en una aplicación de formularios de Windows. –

3

Lo que hace eso asegura que se llama CoInitialize especificando COINIT_APARTMENTTHREADED como el parámetro. Si no utiliza ningún componente COM o control ActiveX, no tendrá ningún efecto sobre usted. Si lo haces, entonces es algo crucial.

Los controles que son roscada de apartamentos son efectivamente de un solo subproceso, llamadas hechas a ellos sólo pueden procesarse en el apartamento que fueron creados en

algo más de detalle de MSDN:.

Los objetos creados en un solo subproceso apartamento (STA) recibir llamadas de método solamente a partir de hilos de su apartamento, así llamadas son serializados y llegar solamente en los límites de mensaje en cola (cuando el PeekMessage función Win32 o se llama SendMessage).

Los objetos creados en un subproceso de COM en un apartamento multiproceso (MTA) deben ser capaz de recibir llamadas a métodos de otros hilos en cualquier momento. Se podría aplicar normalmente algún tipo de control de concurrencia en el código de un objeto de multiproceso utilizando Win32 primitivas de sincronización como críticos secciones, semáforos, o mutex para ayudar a proteger los datos del objeto .

Cuando un objeto que está configurado para de ejecución en el apartamento roscado neutral (NTA) es llamado por un hilo que está en ya sea un STA o la MTA, ese hilo transferencias a la NTA. Si este subproceso posteriormente llama a CoInitializeEx, la llamada falla y devuelve RPC_E_CHANGED_MODE.

+0

El artículo de MSDN es útil desde una perspectiva COM, pero ¿puede decirme cuándo .NET llama a 'CoInitialize()' en respuesta al atributo 'STAThread' /' ApartmentState'? Nota: El artículo en MSDN está aquí: [Función CoInitializeEx] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms695279%28v=vs.85%29.aspx). – jrh

+0

@jrh lo llama cuando se inicia el subproceso –

+0

Hace [thread-> SetApartment] (https://github.com/dotnet/coreclr/blob/master/src/vm/comsynchronizable.cpp#L987) utiliza 'CoInitialize () 'internamente? Rastreé el atributo STAThread todo el camino hasta allí, pero el camino se ha vuelto frío (no puedo encontrar la fuente de 'Thread :: SetApartment'). ¿Está la clase Thread de thread.h (el hilo COM.h) documentado en cualquier lugar? ¿Es MFC, ATL o algo más? – jrh

-14

STAThread se escribe antes de la función principal de un proyecto de GUI de C#. No hace más que permitir que el programa cree un solo hilo.