threading thread start net book .net multithreading com

thread - ¿Debo llamar a CoInitialize antes de interactuar con COM en.NET?



c#.net threading (2)

Para responder a su primera pregunta, si recuerdo correctamente mi Don Box, cada tema DEBE llamar a CoInitialize. Sin excepciones.

En cuanto a la parte automágica, no tengo idea.

Sé que un requisito de COM que cada hilo llame a CoInitialize antes de interactuar con el sistema COM.

.NET expone algunos elementos que operan internamente en hilos, por ejemplo:

Si voy a interactuar con un objeto COM a partir de un hilo, ¿necesito llamar a CoInitialize primero?

Pregunto porque puede haber algo más de magia que automágicamente me llame, no sé.

Lectura de bonificación

Subprocesamiento administrado y no administrado

Para la interoperabilidad, el tiempo de ejecución de lenguaje común crea e inicializa un apartamento cuando se llama a un objeto COM. Un subproceso administrado puede crear e ingresar un apartamento de subproceso único (STA) que contiene solo un subproceso o un apartamento de subprocesos múltiples (MTA) que contiene uno o más subprocesos. Cuando un apartamento COM y un apartamento generado por subprocesos son compatibles, COM permite que el subproceso de llamada realice llamadas directamente al objeto COM. Si los apartamentos son incompatibles, COM crea un apartamento compatible y coordina todas las llamadas a través de un proxy en el nuevo departamento.

El tiempo de ejecución llama a CoInitializeEx para inicializar el apartamento COM como un MTA o un apartamento STA.

Actualización dos:

Parece que no deberías usar COM de ningún tipo de hilo que .NET pueda proporcionar:

El conjunto de hilos gestionados

Hay varios escenarios en los que es apropiado crear y administrar sus propios subprocesos en lugar de utilizar subprocesos de grupo de subprocesos:

  • Usted requiere un hilo de primer plano.

  • Necesita un hilo para tener una prioridad particular.

  • Tiene tareas que hacen que el hilo se bloquee durante largos períodos de tiempo. El grupo de subprocesos tiene un número máximo de subprocesos, por lo que una gran cantidad de subprocesos de grupo de subprocesos bloqueados podría impedir el inicio de tareas.

  • Debe colocar hilos en un apartamento de subproceso único. Todos los hilos ThreadPool están en el apartamento multiproceso.

  • Necesita tener una identidad estable asociada con el hilo, o dedicar un hilo a una tarea.

Actualización tres :

Parece que puede establecer el modelo de subprocesamiento de subprocesos no controlados:

Subprocesamiento administrado y no administrado en Microsoft Windows

Se puede marcar un hilo administrado para indicar que alojará un apartamento de subproceso único o multiproceso. Los métodos GetApartmentState , SetApartmentState y TrySetApartmentState de la clase Thread devuelven y asignan el estado de un subproceso. Si el estado no se ha establecido, GetApartmentState devuelve ApartmentState.Unknown .

La propiedad se puede establecer solo cuando el hilo está en el estado ThreadState.Unstarted ; se puede configurar solo una vez para un hilo.

Si el estado del departamento no está configurado antes de que se inicie el hilo, el hilo se inicializa como un apartamento multiproceso (MTA).

Gran cantidad de información conflictiva.

Por eso usaremos lo que dijo el tipo de Stackoverflow como la verdadera respuesta.


La información aquí no es contradictoria, simplemente no es necesariamente muy claro si eres nuevo en COM.

Respuesta corta:

  • Los hilos de .Net siempre están coinicializados para usted; no tiene que (¡ni debería!) Llamarlo usted mismo.
  • Los subprocesos ThreadPool (y, por lo tanto, cualquier cosa que use subprocesos ThreadPool, como delegados asincrónicos, etc.) siempre se inicializan MTA. La única opción para crear un hilo STA es agregar el atributo [STAThread] a Main() para solicitar que el tiempo de ejecución inicialice el hilo principal como STA, o usar thread.SetApartmentState (ApartmentState.STA) en un hilo nuevo que cree antes de llamar thread.Start() - de lo contrario son MTA por defecto. En cualquier caso, el modelo de apartamento de hilo no se puede modificar una vez que el hilo se inicia y se ejecuta.

Respuesta más larga: hay dos formas de llamar a CoInitialize: puede usarlo para inicializar el hilo como un hilo Single-Threaded Apartment (STA), o como un hilo Multi-Threaded Apartment (MTA). Lo que el texto anterior dice es que, de forma predeterminada, los hilos nuevos y los hilos de subprocesos se preincronizan automáticamente como MTA-flavor. Pero con un nuevo hilo, puede usar ApartmentState para especificar STA-flavor, si lo hace antes de realmente comenzar el hilo. Siempre está coinicializado de una forma u otra para el momento en que se inicia de todos modos.

Tenga en cuenta que Main () en los programas basados ​​en UI está marcado con el atributo [STAThread] para asegurarse de que está basado en STA; mientras que en una aplicación de consola, la falta de [STAThread] significa que está CoInited como MTA. La razón de este atributo, dicho sea de paso, es que el hilo que llama a Main () es el único hilo que no puede especificar STA frente a MTA usando ApartmentState, porque ya se está ejecutando y para cuando se ejecuta Main (), demasiado tarde para usar eso; así que piense en el atributo como una pista al tiempo de ejecución para establecer el estado del departamento antes de llamar a Main ().

La cuestión clave a tener en cuenta es que STA generalmente se utiliza con la interfaz de usuario y requiere un bucle de mensajes (que .Net WinForms proporciona para usted); El código STA nunca debe bloquearse con Sleep () o similar, de lo contrario tu UI también se bloqueará. MTA, por otro lado, está diseñado para el uso de los trabajadores: tareas en segundo plano, descarga de archivos o haciendo cálculos en segundo plano, por ejemplo, y generalmente no debe ser propietario de la IU. Puede utilizar COM desde cualquiera de estos, pero puede depender de lo que esté haciendo el objeto COM o de dónde lo obtuvo. Si se trata de un componente de interfaz de usuario, es probable que desee utilizarlo desde un hilo STA; por otro lado, si se trata de un componente para descargar o hacer cálculos, normalmente lo usaría de un hilo de MTA.

La Actualización 1 anterior básicamente dice que el tiempo de ejecución de .Net siempre llama CoInitialize por usted, pero le permite elegir STA vs MTA, con MTA como predeterminado.

La Actualización 2 anterior básicamente dice que dado que los hilos de ThreadPool son MTA (y no puede cambiar eso), solo debe usarlos para hacer operaciones en segundo plano, y no usarlos para tareas de IU.

La Actualización 3 dice que para los hilos nuevos, puede elegir MTA versus STA, lo mismo que la actualización 1, simplemente siendo más explícito sobre las API.

Todo el asunto MTA vs STA puede volverse bastante complejo, sugiera leer este artículo como punto de partida. El panorama general, sin embargo, se resume principalmente al recordar que STA = hilo único y UI; MTA = hilos múltiples, tareas de fondo / trabajador. (STA frente a MTA también se aplica a objetos, no solo a hilos, y COM hace un montón de trabajo detrás de escena para permitir que los diferentes tipos de hilos usen los diferentes tipos de objetos. Cuando funciona bien, uno no se da cuenta y puede ignorarlo felizmente, pero cuando llegas a una restricción o limitación, a menudo puede ser difícil averiguar qué está pasando).