Procesos, subprocesos y apartamentos

Un proceso es una colección de espacio de memoria virtual, código, datos y recursos del sistema. Un hilo es código que se ejecuta de forma secuencial dentro de un proceso. Un procesador ejecuta subprocesos, no procesos, por lo que cada aplicación tiene al menos un proceso y un proceso siempre tiene al menos un subproceso de ejecución, conocido como subproceso principal. Un proceso puede tener varios subprocesos además del subproceso principal.

Los procesos se comunican entre sí a través de mensajes, mediante la tecnología de llamada a procedimiento remoto (RPC) de Microsoft para pasar información entre sí. No hay ninguna diferencia en el autor de la llamada entre una llamada procedente de un proceso en un equipo remoto y una llamada procedente de otro proceso en la misma máquina.

Cuando un subproceso comienza a ejecutarse, continúa hasta que se elimina o hasta que un subproceso lo interrumpe con mayor prioridad (mediante una acción de usuario o el programador de subprocesos del kernel). Cada subproceso puede ejecutar secciones independientes de código o varios subprocesos pueden ejecutar la misma sección de código. Los subprocesos que ejecutan el mismo bloque de código mantienen pilas separadas. Cada subproceso de un proceso comparte las variables globales y los recursos del proceso.

El programador de subprocesos determina cuándo y con qué frecuencia ejecutar un subproceso, según una combinación del atributo de clase de prioridad del proceso y la prioridad base del subproceso. Para establecer el atributo de clase de prioridad de un proceso, llame a la función SetPriorityClass y establezca la prioridad base de un subproceso con una llamada a SetThreadPriority.

Las aplicaciones multihilo deben evitar dos problemas relacionados con los hilos: interbloqueos y condiciones de carrera. Un interbloqueo se produce cuando cada subproceso espera a que el otro haga algo. El control de llamadas COM ayuda a evitar interbloqueos en llamadas entre objetos. Una condición de carrera se produce cuando un hilo finaliza antes que otro del que depende, lo que hace que el primero use un valor no inicializado porque el segundo aún no ha proporcionado uno válido. COM proporciona algunas funciones diseñadas específicamente para ayudar a evitar condiciones de carrera en servidores fuera del proceso. (Consulte Utilidades auxiliares para la implementación del servidor fuera de proceso.)

El apartment y la arquitectura de subprocesos de COM

Aunque COM admite el modelo de un solo subproceso por proceso frecuente antes de la introducción de varios subprocesos de ejecución, puede escribir código para aprovechar varios subprocesos, lo que da lugar a aplicaciones más eficaces, permitiendo que se ejecute un subproceso mientras otro subproceso espera una operación que tarda mucho tiempo en completarse.

Nota

El uso de varios subprocesos no es una garantía de un mejor rendimiento. De hecho, dado que la factorización de subprocesos es un problema difícil, el uso de varios subprocesos suele provocar problemas de rendimiento. La clave es usar varios hilos solo si está completamente seguro de lo que está haciendo.

 

En general, la forma más sencilla de entender la arquitectura de subprocesos de COM es pensar en todos los objetos COM del proceso divididos en grupos llamados apartments. Un objeto COM reside en un único apartment, en el sentido de que sus métodos solo pueden ser invocados directamente, de forma válida, por un subproceso que pertenezca a ese apartment. Cualquier otro subproceso que quiera llamar al objeto debe pasar por un proxy.

Hay dos tipos de apartamentos: apartamentos de un solo subprocesoy apartamentos multiproceso.

Importante

Elección de un modelo de apartamento (STA frente a MTA):

Apartamento CoInitializeEx Indicador Se utiliza cuando
STA (uniproceso) COINIT_APARTMENTTHREADED El subproceso tiene un bucle de mensajes (subprocesos de interfaz de usuario) o usa objetos COM que requieren una bomba de mensajes (controles ActiveX, objetos Shell, arrastrar y colocar).
MTA (multiproceso) COINIT_MULTITHREADED Tu subproceso realiza tareas en segundo plano sin bucle de mensajes, y los objetos COM que utilizas son seguros para subprocesos o ágiles.

Error común que provoca interbloqueos: Un subproceso STA debe bombear mensajes (a través de GetMessage/DispatchMessage o su equivalente). Si un hilo STA se bloquea en una primitiva de sincronización (por ejemplo, WaitForSingleObject) sin bombear mensajes, las llamadas COM entrantes a los objetos de ese apartamento nunca se entregarán, lo que provocará interbloqueos. Utiliza CoWaitForMultipleHandles o MsgWaitForMultipleObjects en lugar de esperas sin filtrar en un hilo STA.

  • Los apartamentos de un solo subproceso constan exactamente de un subproceso, por lo que todos los objetos COM que residen en un apartamento de un solo subproceso pueden recibir llamadas de método solo desde el subproceso que pertenece a ese apartamento. Todas las llamadas a métodos de un objeto COM en un apartamento de un solo hilo se sincronizan con la cola de mensajes de Windows para el hilo del apartamento de un solo hilo. Un proceso con un único subproceso de ejecución es simplemente un caso especial de este modelo.
  • Los apartamentos multiproceso constan de uno o varios subprocesos, por lo que todos los objetos COM que residen en un apartamento multiproceso pueden recibir llamadas de método directamente desde cualquiera de los subprocesos que pertenecen al apartamento multiproceso. Los hilos de un apartamento multihilo utilizan un modelo denominado free-threading. Las llamadas a objetos COM en un apartamento multiproceso se sincronizan mediante los propios objetos.

Nota

Para obtener una descripción de la comunicación entre apartamentos de un solo subproceso y apartamentos de varios subprocesos dentro del mismo proceso, consulte Comunicación entre subprocesos únicos y varios subprocesos.

 

Un proceso puede tener cero o más apartamentos de un solo hilo y cero o un apartamento multihilo.

En un proceso, el apartamento principal es el primero en inicializarse. En un proceso de un solo hilo, este es el único apartamento. Los parámetros de llamada se organizan para su transferencia entre apartamentos, y COM controla la sincronización mediante mensajes. Si designa varios hilos de un proceso para que sean de ejecución libre, todos los hilos de ejecución libre residen en un solo apartamento, los parámetros se pasan directamente a cualquier hilo del apartamento y debe encargarse de toda la sincronización. En un proceso que cuenta tanto con free-threading como con apartment threading, todos los subprocesos libres residen en un único apartamento y todos los demás apartamentos son de un solo subproceso. Un proceso que realiza tareas COM es un conjunto de apartamentos con, como máximo, un apartamento multihilo, pero con cualquier número de apartamentos de un solo subproceso.

Los modelos de subprocesos de COM proporcionan el mecanismo para los clientes y servidores que usan diferentes arquitecturas de subprocesos para trabajar conjuntamente. Las llamadas entre objetos con diferentes modelos de hilos en distintos procesos se admiten de forma natural. Desde la perspectiva del objeto que realiza la llamada, todas las llamadas a objetos externos a un proceso se comportan de forma idéntica, independientemente del modelo de subprocesos del objeto al que se llama. Del mismo modo, desde la perspectiva del objeto al que se llama, las llamadas entrantes se comportan de forma idéntica, independientemente del modelo de subprocesos del objeto que realiza la llamada.

La interacción entre un cliente y un objeto fuera de proceso es sencilla, incluso cuando usan modelos de subprocesos diferentes porque el cliente y el objeto están en procesos diferentes. COM, interpuesto entre el cliente y el servidor, puede proporcionar el código necesario para que los modelos de subprocesos interactúen entre sí, utilizando marshaling estándar y RPC. Por ejemplo, si varios clientes de subprocesos libres llaman simultáneamente a un objeto de un solo subproceso, COM sincronizará las llamadas colocando los mensajes de ventana correspondientes en la cola de mensajes del servidor. El apartamento del objeto recibirá una llamada cada vez que recupere y envíe mensajes. Sin embargo, se debe tener cuidado para asegurarse de que los servidores en proceso interactúan correctamente con sus clientes. (Consulte Problemas de subprocesamiento del servidor en proceso.)

El problema más importante en la programación con un modelo multiproceso es hacer que el subproceso de código sea seguro para que los mensajes destinados a un subproceso determinado solo vayan a ese subproceso y el acceso a los subprocesos esté protegido.

Para obtener más información, consulte los temas siguientes: