apartamentos de Single-Threaded
El uso de apartamentos de un solo subproceso (el proceso del modelo de apartamento) ofrece un paradigma basado en mensajes para tratar varios objetos que se ejecutan simultáneamente. Permite escribir código más eficaz al permitir que se ejecute un subproceso, mientras espera a que se complete una operación lenta, para permitir que se ejecute otro subproceso.
Cada subproceso de un proceso que se inicializa como un proceso de modelo de apartamento y que recupera y envía mensajes de ventana, es un subproceso de apartamento de un solo subproceso. Cada hilo vive dentro de su propio apartamento. Dentro de un apartamento, se pueden pasar punteros de interfaz sin serializar y, por lo tanto, todos los objetos de un subproceso de apartamento de un solo subproceso se comunican directamente.
Una agrupación lógica de objetos relacionados que se ejecutan en el mismo subproceso y, por lo tanto, debe tener una ejecución sincrónica, podría residir en el mismo subproceso de contenedor de un solo subproceso. Sin embargo, un objeto de modelo de apartamento no puede residir en más de un subproceso. Las llamadas a objetos de otros subprocesos se deben realizar dentro del contexto del subproceso propietario, por lo que com distribuido cambia los subprocesos automáticamente cuando se llama a en un proxy.
Los modelos de interproceso e interproceso son similares. Cuando es necesario pasar un puntero de interfaz a un objeto de otro apartamento (en otro subproceso) dentro del mismo proceso, se usa el mismo modelo de serialización que los objetos de distintos procesos usan para pasar punteros a través de los límites del proceso. Al obtener un puntero al objeto de serialización estándar, puede serializar punteros de interfaz entre límites de subprocesos (entre apartamentos) de la misma manera que hace entre procesos. (Los punteros de interfaz deben serializarse cuando se pasan entre apartamentos).
Las reglas para apartamentos de un solo subproceso son sencillas, pero es importante seguirlas cuidadosamente:
- Cada objeto debe residir solo en un subproceso (dentro de un contenedor de un solo subproceso).
- Inicialice la biblioteca COM para cada subproceso.
- Serializa todos los punteros a objetos al pasarlos entre apartamentos.
- Cada apartamento de un solo subproceso debe tener un bucle de mensajes para controlar las llamadas de otros procesos y apartamentos dentro del mismo proceso. Los apartamentos de un solo subproceso sin objetos (solo cliente) también necesitan un bucle de mensajes para enviar los mensajes de difusión que usan algunas aplicaciones.
- Los objetos basados en DLL o en proceso no llaman a las funciones de inicialización COM; en su lugar, registran su modelo de subprocesos con el valor con nombre ThreadingModel en la clave InprocServer32 del Registro. Los objetos compatibles con el apartamento también deben escribir puntos de entrada dll cuidadosamente. Hay consideraciones especiales que se aplican a los servidores en proceso de subprocesos. Para obtener más información, vea Problemas de subprocesos del servidor en proceso.
Aunque varios objetos pueden residir en un único subproceso, ningún objeto de modelo de apartamento puede residir en más de un subproceso.
Cada subproceso de un proceso de cliente o un servidor fuera de proceso debe llamar a CoInitialize o llamar a CoInitializeEx y especificar COINIT_APARTMENTTHREADED para el parámetro dwCoInit . El apartamento principal es el subproceso que llama primero a CoInitializeEx . Para obtener información sobre los servidores en proceso, vea Problemas de subprocesos del servidor en proceso.
Todas las llamadas a un objeto deben realizarse en su subproceso (dentro de su apartamento). Está prohibido llamar a un objeto directamente desde otro subproceso; el uso de objetos de esta manera sin subprocesos podría causar problemas para las aplicaciones. La implicación de esta regla es que todos los punteros a objetos deben serializarse cuando se pasan entre apartamentos. COM proporciona las dos funciones siguientes para este propósito:
- CoMarshalInterThreadInterfaceInStream serializa una interfaz en un objeto de secuencia que se devuelve al autor de la llamada.
- CoGetInterfaceAndReleaseStream desmarshala un puntero de interfaz de un objeto de secuencia y lo libera.
Estas funciones encapsulan las llamadas a las funciones CoMarshalInterface y CoUnmarshalInterface , que requieren el uso de la marca MSHCTX_INPROC.
En general, com realiza automáticamente la serialización. Por ejemplo, al pasar un puntero de interfaz como parámetro en una llamada de método en un proxy a un objeto de otro apartamento, o al llamar a CoCreateInstance, COM realiza la serialización automáticamente. Sin embargo, en algunos casos especiales, donde el escritor de aplicaciones pasa punteros de interfaz entre apartamentos sin usar los mecanismos COM normales, el escritor debe controlar manualmente la serialización.
Si un apartamento (Apartamento 1) en un proceso tiene un puntero de interfaz y otro apartamento (Apartamento 2) requiere su uso, Apartment 1 debe llamar a CoMarshalInterThreadInterfaceInStream para serializar la interfaz. La secuencia creada por esta función es segura para subprocesos y debe almacenarse en una variable accesible por Apartment 2. Apartment 2 debe pasar esta secuencia a CoGetInterfaceAndReleaseStream para desmarshalar la interfaz y recuperará un puntero a un proxy a través del cual puede acceder a la interfaz. El apartamento principal debe permanecer activo hasta que el cliente haya completado todo el trabajo COM (porque algunos objetos en proceso se cargan en el apartamento principal, como se describe en Problemas de subprocesos del servidor en proceso). Después de pasar un objeto entre subprocesos de esta manera, es muy fácil pasar punteros de interfaz como parámetros. De este modo, COM distribuido realiza la serialización y el cambio de subprocesos para la aplicación.
Para controlar las llamadas de otros procesos y apartamentos dentro del mismo proceso, cada apartamento de un solo subproceso debe tener un bucle de mensajes. Esto significa que la función de trabajo del subproceso debe tener un bucle GetMessage/DispatchMessage. Si se usan otros primitivos de sincronización para comunicarse entre subprocesos, se puede usar la función MsgWaitForMultipleObjects para esperar mensajes y eventos de sincronización de subprocesos. La documentación de esta función tiene un ejemplo de este tipo de bucle de combinación.
COM crea una ventana oculta con la clase "OleMainThreadWndClass" de Windows en cada apartamento de un solo subproceso. Se recibe una llamada a un objeto como un mensaje de ventana a esta ventana oculta. Cuando el apartamento del objeto recupera y envía el mensaje, la ventana oculta la recibirá. A continuación, el procedimiento de ventana llamará al método de interfaz correspondiente del objeto .
Cuando varios clientes llaman a un objeto, las llamadas se ponen en cola en la cola de mensajes y el objeto recibirá una llamada cada vez que su apartamento recupera y envía mensajes. Dado que com sincroniza las llamadas y el subproceso que pertenece al apartamento del objeto siempre entrega las llamadas, las implementaciones de la interfaz del objeto no necesitan proporcionar sincronización. Los apartamentos de un solo subproceso pueden implementar IMessageFilter para permitirles cancelar llamadas o recibir mensajes de ventana cuando sea necesario.
El objeto se puede volver a escribir si una de sus implementaciones del método de interfaz recupera y envía mensajes o realiza una llamada ORPC a otro subproceso, lo que hace que otra llamada se entregue al objeto (por el mismo apartamento). OLE no evita la reentrada en el mismo subproceso, pero puede ayudar a proporcionar seguridad para subprocesos. Esto es idéntico al modo en que se puede volver a escribir un procedimiento de ventana si recupera y envía mensajes mientras procesa un mensaje. Sin embargo, al llamar a un servidor de apartamentos de un solo subproceso fuera de proceso que llama a otro servidor de apartamentos de un solo subproceso, se permitirá que se vuelva a escribir el primer servidor.
Temas relacionados