INFO: Descripción y funcionamiento de los modelos de subprocesamiento de OLE


Resumen


Los objetos COM se pueden utilizar en varios subprocesos de un proceso. Los términos "apartamento solo encadenada" (STA) y "Multi-Threaded Apartment" (MTA) se utilizan para crear un marco conceptual para describir la relación entre objetos y subprocesos, las relaciones de simultaneidad entre objetos, los medios mediante el método las llamadas se entregan a un objeto y las reglas para pasar punteros de interfaz entre subprocesos. Componentes y sus clientes elegir entre los siguientes modelos de dos apartamento actualmente compatibles con COM:

  1. Modelo de apartamento de un único subproceso (STA): uno o varios subprocesos en un proceso de utilizan COM ni llamadas a objetos COM se sincronizan mediante Interfaces COM se calculan sus referencias entre subprocesos. Un caso degeneración del modelo de apartamento de un único subproceso, donde COM utiliza sólo un subproceso de un proceso determinado, se denomina modelo de subprocesamiento único. Anterior documentación e información de Microsoft se denomina el modelo STA simplemente el "modelo de apartamento".
  2. Modelo de apartamento multiproceso (MTA): uno o más subprocesos utilizan COM y se efectúan llamadas a objetos COM asociados con el MTA directamente por todos los subprocesos asociados con el MTA sin ninguna interposición de código entre el llamador y el objeto del sistema. Dado que varios clientes simultáneos puedan llamar objetos más o menos simultáneamente (simultáneamente en sistemas multiprocesadores), objetos deben sincronizar su estado interno por sí mismos. Las interfaces no se calculan referencias entre subprocesos. Anterior documentación e información de Microsoft se denomina a este modelo el "modelo de subprocesamiento libre."
  3. El modelo STA y el modelo MTA pueden utilizarse en el mismo proceso. Esto se conoce a veces como un proceso de "modelo mixto".
El MTA se presentó en NT 4.0 y está disponible en Windows 95 con DCOM95. El modelo STA existe en Windows NT 3.51 y Windows 95 como NT 4.0 y Windows 95 con DCOM95.

Más información


Información general

Los modelos de subprocesamiento de COM proporcionan el mecanismo para los componentes que utilizan distintas arquitecturas de subprocesamiento para trabajar juntos. También proporcionan servicios de sincronización a los componentes que los necesitan. Por ejemplo, un objeto determinado puede estar diseñado para ser llamado solo por un único subproceso y no puede sincronizar las llamadas simultáneas desde clientes. Si se llama a este tipo de objeto simultáneamente por varios subprocesos, se bloquea o causa errores. COM proporciona los mecanismos para tratar con esta interoperabilidad de arquitecturas de subprocesamiento.

Incluso subprocesos componentes a menudo necesitan servicios de sincronización. Por ejemplo, los componentes que tienen una interfaz gráfica de usuario (GUI), como controles OLE/ActiveX, incrustaciones activo en contexto y documentos de ActiveX, requieren la sincronización y la serialización de llamadas de COM y mensajes de ventana. COM proporciona estos servicios de sincronización para que estos componentes pueden escribirse sin código complejo de sincronización.

Un "apartamento" tiene varios aspectos relacionados entre sí. En primer lugar, es una construcción lógica para pensar acerca de la concurrencia, por ejemplo, cómo se relacionan los subprocesos a un conjunto de objetos COM. En segundo lugar, es que un conjunto de programadores de reglas debe obedecer para recibir el comportamiento de concurrencia que se esperan del entorno COM. Finalmente, es el código proporcionado por el sistema que ayuda a los programadores administrar la simultaneidad de subprocesos con respecto a los objetos COM.

El término "apartamento" proviene de una metáfora en la que un proceso se concibe como una entidad totalmente discreta, como un "edificio" está dividido en un conjunto de diferentes pero relacionadas "locales" denominado "departamentos". Un apartamento es un "contenedor lógico" que crea una asociación entre objetos y, en algunos casos, los subprocesos. Subprocesos no son apartamentos, aunque puede haber un único subproceso asociado lógicamente a un apartamento en el modelo STA. Los objetos no son apartamentos, aunque cada objeto está asociado con una y solamente una apartamento. Pero los apartamentos son algo más que una construcción lógica; las reglas describen el comportamiento del sistema COM. Si no se siguen las reglas de los modelos de apartamento, objetos COM no funcionará correctamente.

Más detalles

Un apartamento de un único subproceso (STA) es un conjunto de objetos COM asociado con un subproceso en particular. Estos objetos están asociados con el apartamento por ser creados por el subproceso o, más exactamente, primero exponerse en el sistema COM (normalmente por el cálculo de referencias) en el subproceso. UN STA se considera un lugar donde un objeto o un servidor proxy "vive". Si necesita tener acceso a otro departamento (en un proceso diferente o el mismo) del objeto o del proxy, debe calcularse su puntero de interfaz a ese departamento donde se crea un nuevo proxy. Si se siguen las reglas del modelo de apartamento, no hay llamadas directas desde otros subprocesos en el mismo proceso se permiten en el objeto; que infringiría la regla en la que todos los objetos dentro de un apartamento dado se ejecutan en un único subproceso. La regla existe porque la mayoría del código se ejecuta en un STA no funcionará correctamente si se ejecutan en subprocesos adicionales.

El subproceso asociado a un STA debe llamar a CoInitialize o CoInitializeEx (NULL, COINIT_APARTMENTTHREADED) y debe recuperar y enviar mensajes de ventana para los objetos asociados recibir llamadas entrantes. COM se distribuye y sincroniza las llamadas a objetos en un STA mediante mensajes de ventana, como se describe más adelante en este artículo.

"El STA principal" es el subproceso que llama a CoInitialize o CoInitializeEx(NULL,COINIT_APARTMENTTHREADED) en primer lugar dentro de un proceso determinado. El STA principal de un proceso debe permanecer activo hasta que se completa todo el trabajo COM porque algunos objetos en un proceso siempre se cargan en el STA principal, tal como se describe más adelante en este artículo.

Windows NT 4.0 y DCOM95 introducen a un nuevo tipo de apartamento llamada al apartamento multiproceso (MTA). Un MTA es un conjunto de objetos COM asociados a un conjunto de subprocesos en el proceso de forma que cualquier subproceso puede llamar a cualquier implementación de objeto directamente sin la interposición de código del sistema. Pueden pasar entre los subprocesos asociados con el MTA sin necesidad de calcular las referencias de punteros de interfaz a cualquier objeto en el MTA. Todos los subprocesos en el proceso que llama a CoInitializeEx (NULL, COINIT_MULTITHREADED) están asociados con el MTA. A diferencia de lo STA descrito anteriormente, los subprocesos en un MTA no es necesario recuperar y enviar mensajes de ventana para los objetos asociados recibir llamadas entrantes. COM no sincronizar las llamadas a objetos en un MTA. Objetos en un MTA deben proteger su estado interno de daños por la interacción de varios subprocesos simultáneos y no pueden hacer ninguna suposición sobre el contenido de la constante restante del almacenamiento Local de subprocesos entre las distintas invocaciones de método diferentes.

Un proceso puede tener cualquier número de emisoras pero, como máximo, puede tener un MTA. El MTA está formado por uno o varios subprocesos. STAs tienen un subproceso. Un subproceso pertenece, a lo sumo, un apartamento. Los objetos pertenecen a una y solamente una apartamento. Punteros de interfaz siempre deben calcularse entre apartamentos (aunque puede ser el resultado de calcular referencias de un puntero directo en lugar de un servidor proxy). Vea información debajo de CoCreateFreeThreadedMarshaler.

Un proceso elige uno de los modelos de subprocesamiento proporcionados por COM. Un proceso de modelo STA tiene uno o más emisoras y no tiene un MTA. Un proceso de modelo MTA tiene un MTA con uno o más subprocesos y no tiene ningún STAs. Un proceso de modelo mixto tiene un MTA y cualquier número de emisoras.

Modelo de apartamento de un único subproceso

El subproceso de un STA debe llamar a CoInitialize o CoInitializeEx (NULL, COINIT_APARTMENTTHREADED) y debe recuperar y enviar mensajes de ventana, ya que COM utiliza mensajes de ventana para sincronizar y envío a la entrega de las llamadas a un objeto de este modelo. Consulte la sección referencias a continuación para obtener más información.

Servidor que admita el modelo STA:

En el modelo STA, las llamadas a un objeto se sincronizan mediante COM de la misma manera como se sincronizan los mensajes de ventana en una ventana. Las llamadas se entregan mediante mensajes de ventana al subproceso que creó el objeto. Por consiguiente, el subproceso del objeto debe llamar a Get/PeekMessage y DispatchMessage para recibir llamadas. COM crea una ventana oculta asociada con cada STA. Una llamada a un objeto desde fuera el STA se transfiere en tiempo de ejecución COM al subproceso del objeto mediante un mensaje de ventana registrado en esta ventana oculta. Cuando el subproceso asociado STA del objeto se recupera y envía el mensaje, el procedimiento de ventana para la ventana oculta, que también se implementa por COM, lo recibe. El procedimiento de ventana se utiliza por el runtime de COM para el subproceso asociado el STA porque el tiempo de ejecución de COM está en ambos lados de la llamada del subproceso de COM de propiedad a los subprocesos del STA de "enlace". El runtime de COM (que ahora se ejecutan en subprocesos del STA) se llama "arriba" a través de un código auxiliar proporcionado por COM en el método de interfaz correspondiente del objeto. La ruta de ejecución volver de la llamada al método invierte la llamada "arriba"; la llamada devuelve hasta el código auxiliar y el runtime de COM, que pasa el control al subproceso de tiempo de ejecución de COM a través de un mensaje de ventana, a continuación, se devuelve a través del canal de COM al llamador original.

Cuando varios clientes llaman un objeto STA, las llamadas automáticamente en espera en la cola de mensajes por la transferencia del mecanismo de control utilizado en el STA. El objeto recibe una llamada cada vez que su STA recupera y envía mensajes. Puesto que las llamadas se sincronizan mediante COM de esta manera, y las llamadas siempre se entregan en el único subproceso asociado STA del objeto, las implementaciones de interfaz del objeto no es necesario proporcionar sincronización.

Nota: el objeto se puede volver a entrar si una implementación de método de interfaz recupera y envía mensajes al procesar una llamada al método, causando otra llamada a entregarse al objeto el mismo STA. Una forma habitual en el que esto ocurre es que si un objeto STA hace una llamada (cross-apartamento o entre procesos) saliente mediante COM. Esto es idéntico a la manera en la que un procedimiento de ventana puede ser reintroducido si recupera y envía mensajes al procesar un mensaje. COM no impide la entrada de re en el mismo subproceso, pero impide que la ejecución simultánea. También proporciona un medio por el cual puede administrarse reentrada relacionados con COM. Consulte la sección referencias a continuación para obtener más información. El objeto no es re-escrito si las implementaciones de método no llamar fuera de su apartamento o lo contrario recuperar y enviar mensajes.

Responsabilidades del cliente en el modelo STA:

Código de cliente que se ejecuta en un proceso o subproceso que utiliza el modelo STA debe calcular referencias de interfaces de un objeto entre apartamentos mediante CoMarshalInterThreadInterfaceInStream y CoGetInterfaceAndReleaseStream. Por ejemplo, si apartamento 1 en el cliente tiene un puntero de interfaz y apartamento 2 requiere el uso de la misma, apartamento 1 debe calcular las referencias de la interfaz mediante CoMarshalInterThreadInterfaceInStream. El objeto de secuencia devuelto por esta función es segura para subprocesos y su puntero de interfaz debe almacenarse en una variable de memoria directamente accesible por apartamento 2. Apartamento 2 debe pasar esta interfaz de secuencia a CoGetInterfaceAndReleaseStream deserializar la interfaz en el objeto subyacente y obtener un puntero a un proxy a través del cual puede obtener acceso al objeto.

El apartamento principal de un proceso determinado debe permanecer activo hasta que el cliente haya completado todo el trabajo COM porque algunos objetos en proceso se cargan en el apartamento de main. (Más información se detalla a continuación).

Modelo de apartamento multiproceso

Un MTA es la colección de objetos creados o expuestos por todos los subprocesos en el proceso que llamaran a CoInitializeEx (NULL, COINIT_MULTITHREADED).

Nota: las implementaciones actuales de COM permiten un subproceso que no se inicializan explícitamente COM para formar parte del MTA. Un subproceso que no se inicializa COM forma parte del MTA sólo si se inicia mediante COM después de al menos un otro subproceso en el proceso previamente llamado a CoInitializeEx (NULL, COINIT_MULTITHREADED). (Incluso es posible que el propio COM puede haber inicializado el MTA cuando ningún subproceso cliente explícitamente lo ha hecho; por ejemplo, un subproceso asociado con un STA llama a CoGetClassObject o CoCreateInstance [Ex] en un CLSID que se marca "ThreadingModel = libre" y COM crea de forma implícita un MTA en el que se carga el objeto de clase.) Consulte la información sobre interoperabilidad del modelo siguiente de subprocesos.

Sin embargo, ésta es una configuración que podría causar problemas, como infracciones de acceso, en determinadas circunstancias. Por lo tanto, se recomienda encarecidamente que cada subproceso que necesita para realizar trabajo de COM inicializar COM llamando a CoInitializeEx y al término del trabajo de COM, a continuación, llamar a CoUninitialize. El costo de "innecesariamente" Inicializando un MTA es mínimo.

Threads MTA no es necesario recuperar y enviar mensajes porque COM no utiliza mensajes de ventana en este modelo para entregar llamadas a un objeto.

Servidor que admite el modelo MTA:

En el modelo MTA, llame a un objeto no está sincronizados en múltiples COM. clientes simultáneamente pueden llamar a un objeto que admite este modelo en distintos subprocesos y el objeto debe proporcionar sincronización en sus implementaciones de interfaz o método mediante objetos de sincronización, como eventos, exclusiones mutuas, semáforos, etcetera. Objetos MTA pueden recibir llamadas simultáneas de varios clientes de fuera de proceso a través de un grupo de subprocesos creados por COM que pertenecen al proceso del objeto. Objetos MTA pueden recibir llamadas simultáneas de varios clientes en proceso en varios subprocesos asociados con el MTA.

Responsabilidades del cliente en el modelo MTA:

No tiene código de cliente que se ejecuta en un proceso o subproceso que utiliza el modelo MTA calcular referencias de punteros de interfaz de un objeto entre sí mismo y a otros subprocesos MTA. En su lugar, un subproceso MTA puede utilizar un puntero de interfaz obtenido de otro subproceso MTA como un puntero directo a la memoria. Cuando un subproceso de cliente hace una llamada a un objeto fuera de proceso, se suspende hasta que haya finalizado la llamada. Las llamadas pueden llegar en objetos asociados con el MTA, mientras se bloquean todos los subprocesos creado en la aplicación asociados con el MTA en llamadas fuera de va. En este caso y en general, las llamadas entrantes se entregan en proporcionadas por el runtime de COM de subprocesos. Filtros de mensajes (IMessageFilter) no están disponibles para su uso en el modelo MTA.

Modelo de subprocesamiento mixto

Un proceso que admite el modelo de subprocesamiento mixto utilizará un MTA y STA de uno o más. Punteros de interfaz deben calcularse entre todos los apartamentos, pero pueden utilizarse sin el cálculo de referencias dentro del MTA. Llamadas a objetos en un STA COM para ejecutarse únicamente en un subproceso mientras que las llamadas a objetos en el MTA no se sincronizarán. Sin embargo, llamadas desde un STA a un MTA normalmente atraviesan el código proporcionado por el sistema y cambiar desde el subproceso STA en un subproceso MTA antes de entregárselo al objeto.

Nota: consulte la documentación de SDK en CoCreateFreeThreadedMarshaler() y la explicación de dicha API a continuación para obtener información sobre dónde se pueden utilizar punteros directos de los casos y, en primer lugar cómo un subproceso STA puede llamar directamente a un objeto asociado con el MTA y, a la inversa, desde varios departamentos.

Elegir el modelo de subprocesamiento

Puede elegir un componente admitir el modelo STA, el modelo MTA o una combinación de los dos mediante el modelo de subprocesamiento mixto. Por ejemplo, puede elegir un objeto que hace amplia i/OS admitir MTA para proporcionar una respuesta máxima a los clientes al permitir llamadas a la interfaz realizarse durante la latencia de E/S. O bien, un objeto que interactúa con el usuario casi siempre elige admitir STA para sincronizar las llamadas entrantes de COM con sus operaciones de interfaz gráfica de usuario. Admitir el modelo STA es más fácil porque COM proporciona sincronización. Compatible con el modelo MTA es más difícil porque el objeto debe implementar la sincronización, pero la respuesta a los clientes es mejor, porque la sincronización se usa para pequeñas secciones de código, en lugar de la llamada de toda la interfaz proporcionada por COM.

También se utiliza el modelo STA con Microsoft Transaction Server (MTS, anteriormente "Viper"), y por tanto objetos basado en DLL planea ejecutar en el entorno MTS deberían usar el modelo STA. Objetos implementados para el modelo MTA normalmente funcionará correctamente en un entorno de MTS. Sin embargo, se ejecutarán menos eficaz ya que van a utilizar a las primitivas de sincronización de subproceso innecesario.

Marcar el modelo de subprocesamiento compatibles de servidores en proceso

Un subproceso utiliza el modelo MTA si llama a CoInitializeEx (NULL, COINIT_MULTITHREADED) o utiliza COM sin inicializarla. Un subproceso utiliza el modelo STA si llama a CoInitialize o CoInitializeEx (NULL, COINIT_APARTMENTTHREADED).

Las API de CoInitialize proporcionan control de apartamento de código de cliente y de los objetos que están empaquetados en. Exe, porque el código de inicio del runtime de COM puede inicializar COM de la manera deseada.

Sin embargo, un servidor COM (basado en DLL) en proceso de llamar a CoInitialize o CoInitializeEx porque esas API habrá sido llamadas por el tiempo que el servidor DLL se carga. Por lo tanto, un servidor DLL debe utilizar el registro para informar a COM, el modelo de subprocesamiento que admite para que COM puede asegurarse de que el sistema funciona de manera que sea compatible con él. Un valor de clave de CLSID\InprocServer32 del componente denominado ThreadingModel con nombre se utiliza para este propósito como sigue:

  • Valor de ThreadingModel no está presente: soporta el modelo de subprocesamiento único.
  • ThreadingModel = Apartment: admite STA modelo.
  • ThreadingModel = Both: admite modelo STA y MTA.
  • ThreadingModel = libre: admite sólo MTA.
Nota: ThreadingModel es un valor con nombre, no una subclave de InprocServer32 documentada incorrectamente como en algunas versiones anteriores de la documentación de Win32.

Modelos de subprocesamiento de servidores en proceso se describen más adelante en este artículo. Si un servidor en proceso proporciona muchos tipos de objetos (cada uno con su propio CLSID único), cada tipo puede tener un valor ThreadingModel diferente. En otras palabras, el modelo de subprocesamiento es por CLSID, no por el paquete o la DLL de código. Sin embargo, la entrada de API señala necesarios para "iniciar" y consultan todos los servidores en proceso (DLLGetClassObject(), DLLCanUnloadNow()) debe ser seguro para subprocesos para cualquier servidor en proceso que admite varios subprocesos (lo que significa un valor ThreadingModel de apartamento, ambos, o libre ).

Como los servidores indicados anteriormente, fuera de proceso no marcan ellos mismos utilizando el valor de ThreadingModel. En su lugar, utilizan CoInitialize o CoInitializeEx. Servidores basados en DLL que esperan ejecutar fuera de proceso mediante la funcionalidad de "suplentes" de COM (como el suplente proporcionado por el sistema DLLHOST. (EXE) basta con que siga las reglas para servidores basados en DLL; en ese caso, hay ninguna consideración especial.

Cuando el cliente y el objeto de utilizan distintos modelos de subprocesamiento

Interacción entre un cliente y un objeto fuera de proceso es sencillo incluso cuando se utilizan distintos modelos de subprocesamiento porque el cliente y el objeto están en diferentes procesos y COM está implicado en el paso de llamadas desde el cliente al objeto. Dado que COM se interpone entre el cliente y el servidor, proporciona el código para la interoperación de los modelos de subprocesamiento. Por ejemplo, si un objeto STA se llama simultáneamente varios STA o MTA clientes, COM sincroniza las llamadas colocando mensajes de ventana correspondiente en la cola de mensajes del servidor. STA del objeto recibe una llamada cada vez que recupera y envía mensajes. Todas las combinaciones de interoperabilidad del modelo de subprocesamiento se permite y totalmente compatibles entre clientes y objetos fuera de proceso.

Interacción entre un cliente y un objeto en un proceso que utiliza distintos modelos de subprocesamiento es más complicado. Aunque el servidor está en proceso, COM debe interponer a sí mismo entre el cliente y el objeto en algunos casos. Por ejemplo, un objeto en un proceso diseñado para admitir el modelo STA puede llamar simultáneamente por varios subprocesos de un cliente. COM no puede permitir que al cliente subprocesos acceder directamente a la interfaz del objeto porque el objeto no está diseñado para tal acceso simultáneo. En su lugar, COM debe garantizar que las llamadas son sincronizadas y realizadas exclusivamente por el subproceso asociado el STA que "contiene" el objeto. A pesar de la complejidad agregada, se permiten todas las combinaciones de interoperabilidad del modelo de subprocesamiento entre clientes y objetos en proceso.

Modelos de fuera de proceso (EXE) servidores de subprocesamiento

Los siguientes son tres categorías de servidores fuera de proceso, cada uno de los cuales puede utilizarse cualquier cliente COM independientemente del modelo de subprocesamiento utilizado por ese cliente:

  1. Servidor de modelo STA:

    El servidor realiza trabajo COM en uno o más emisoras. Llamadas entrantes se sincronizan mediante COM y entregadas por el subproceso asociado el STA en el que se creó el objeto. Llamadas de método de generador de clases son entregadas por el subproceso asociado el STA que registra el generador de clases. El objeto y el generador de clases no es necesario implementar la sincronización. Sin embargo, el implementador debe sincronizar el acceso a las variables globales de varias emisoras. El servidor debe utilizar CoMarshalInterThreadInterfaceInStream y CoGetInterfaceAndReleaseStream para calcular referencias de punteros de interfaz, posiblemente desde otros servidores, entre STAs. El servidor, opcionalmente, puede implementar IMessageFilter en cada STA para controlar aspectos de la entrega de la llamada COM. Un caso degenerado es el servidor de modelo de subprocesamiento único que funciona COM en un STA.
  2. Servidor de modelo MTA:

    El servidor realiza trabajo COM en uno o más subprocesos que pertenecen al MTA. Las llamadas no se sincronizan mediante COM. COM crea un grupo de subprocesos en el proceso del servidor, y una llamada de cliente se entrega por cualquiera de estos subprocesos. Subprocesos no necesitan recuperar y enviar mensajes. La fábrica de objeto y una clase debe implementar la sincronización. El servidor no necesita calcular referencias de punteros de interfaz entre subprocesos.
  3. Servidor de modelo mixto:

    Consulte la sección de este artículo titulada "Mixed-threading modelo" para obtener más información.

Modelos en los clientes de subprocesamiento

Hay tres categorías de clientes:

  1. Cliente del modelo STA:

    El cliente funciona COM en subprocesos asociados con uno o más emisoras. El cliente debe utilizar CoMarshalInterThreadInterfaceInStream y CoGetInterfaceAndReleaseStream para calcular referencias de punteros de interfaz entre STAs. Un caso degenerado es el cliente del modelo de subprocesamiento único que funciona COM en un STA. Subproceso del cliente entra en un COM proporcionado el bucle de mensajes cuando realiza una llamada saliente. El cliente puede utilizar IMessageFilter para administrar las devoluciones de llamada y el procesamiento de mensajes de ventana durante la espera en salientes llamadas y otros problemas de concurrencia.
  2. Cliente del modelo de MTA:

    El cliente funciona COM en uno o más subprocesos que pertenecen al MTA. El cliente no necesita calcular referencias de punteros de interfaz entre subprocesos. El cliente no puede utilizar IMessageFilter. Suspensión subprocesos del cliente cuando realiza una llamada de COM a un objeto fuera de proceso y se reanuda cuando finaliza la llamada. Llamadas entrantes llegan en los subprocesos creados por COM y administrados.
  3. Cliente de modelo mixto:

    Consulte la sección de este artículo titulada "Mixed-threading modelo" para obtener más información.

Subprocesamiento modelos en los servidores en proceso (basado en DLL):

Hay cuatro categorías de servidores en proceso, cada uno de los cuales puede utilizarse cualquier cliente COM independientemente del modelo de subprocesamiento utilizado por ese cliente. Sin embargo, los servidores en proceso deben proporcionar código de cálculo de referencias para cualquier interfaz personalizada (no-definidas por el sistema) si son compatibilidad con interoperabilidad de modelo de subprocesamiento, ya que normalmente requiere ese cálculo de referencias COM implementan la interfaz entre el cliente apartamentos. Las cuatro categorías son:

  1. Servidor en proceso que admita subprocesamiento de único (STA "main")-ningún valor de ThreadingModel:

    Se espera un objeto proporcionado por este servidor tener acceso a la misma STA de cliente por el que se creó. Además, el servidor espera a que todos sus puntos de entrada, como DllGetClassObject DllCanUnloadNow y datos globales para el acceso desde el mismo subproceso (uno asociado el STA principal). Servidores que existían antes de la introducción de multi-threading en COM están en esta categoría. Estos servidores no están diseñados para tener acceso a varios subprocesos para COM crea todos los objetos proporcionados por el servidor en el STA principal del proceso y las llamadas a los objetos que se entregan por el subproceso asociado el STA principal. Otros apartamentos de cliente obtener acceso al objeto a través de proxy. Llamadas de los otros apartamentos ir desde el servidor proxy para el código auxiliar en el STA principal (cálculo de referencias entre subprocesos) y, a continuación, el objeto. Este cálculo de referencias permite a sincronizar las llamadas al objeto COM y las llamadas son entregadas por el STA en el que se creó el objeto. El cálculo de referencias entre subprocesos es lenta en comparación con la llamada directa, por lo que se recomienda que estos servidores se ha reescrito para admitir varias emisoras (categoría 2).
  2. Servidor en proceso que admite el modelo de apartamento de subproceso único (STA varios) - marcados con ThreadingModel = Apartment:

    Se espera un objeto proporcionado por este servidor tener acceso a la misma STA de cliente por el que se creó. Por lo tanto, es similar a un objeto proporcionado por un servidor de un único subproceso en un proceso. Sin embargo, pueden crearse objetos proporcionados por este servidor en varias emisoras del proceso, por lo que el servidor debe diseñar sus puntos de entrada, como DllGetClassObject, DllCanUnloadNow y datos globales para el uso de subprocesos múltiples. Por ejemplo, si dos emisoras de un proceso de crean dos instancias del objeto en el proceso simultáneamente, DllGetClassObject puede llamar simultáneamente por ambas emisoras. De forma similar, DllCanUnloadNow debe estar escrito para que el servidor esté protegido de descarga mientras todavía se está ejecutando código en el servidor.

    Si el servidor proporciona sólo una instancia de la fábrica de clase para crear todos los objetos, la implementación de fábrica de clase también debe diseñarse para uso multiproceso porque éste es accedido por múltiples clientes STAs. Si el servidor crea una nueva instancia de la fábrica de clase cada vez que se llama DllGetClassObject, el generador de clases no necesita ser seguro para subprocesos. Sin embargo, el implementador debe sincronizar el acceso a las variables globales.

    Los objetos COM creados por el generador de clases no es necesario ser seguro para subprocesos. Sin embargo, el acceso de las variables globales debe estar sincronizado por el implementador. Una vez creado por un subproceso, es siempre obtiene acceso al objeto a través de que el subproceso y todas las llamadas al objeto se sincronizan mediante apartamentos COM. cliente que sean diferentes de lo STA en el que se creó el objeto debe tener acceso al objeto a través de proxy. Estos servidores proxy se crean cuando el cliente calcula las referencias a la interfaz entre sus departamentos.

    Cualquier cliente que crea un objeto STA a través de su fábrica de clase obtiene un puntero directo al objeto. Esto es diferente de los objetos de un único subproceso en un proceso, donde sólo el STA principal del cliente obtiene un puntero directo al objeto y todas las demás emisoras que crean el objeto ganancia de acceso al objeto a través de un proxy. Dado que el cálculo de referencias entre subprocesos es lenta en comparación con una llamada directa, velocidad puede mejorarse significativamente cambiando a un servidor de un único subproceso en un proceso para admitir varias emisoras.
  3. Servidor en proceso que admite sólo MTA - marcados con ThreadingModel = libre:

    Es seguro para el MTA sólo un objeto proporcionado por este servidor. Implementa su propia sincronización y tengan acceso varios subprocesos de cliente al mismo tiempo. Este servidor puede tener un comportamiento que no es compatible con el modelo STA. (Por ejemplo, su uso de la cola de mensajes de Windows de manera que interrumpe el suministro de mensajes de STA.) Además, marcando el modelo de subprocesamiento del objeto como "Libre", el implementador del objeto indica lo siguiente: este objeto se puede llamar desde cualquier subproceso del cliente, pero este objeto también puede pasar punteros de interfaz directamente (sin cálculo de referencias) a todos los subprocesos que se crea y estos subprocesos pueden realizar llamadas a través de estos punteros. Por lo tanto, si el cliente pasa un puntero de interfaz a un objeto implementado por el cliente (por ejemplo, un receptor) a este objeto, puede volver a llamar a través de este puntero de interfaz desde cualquier subproceso que creó. Si el cliente es un STA, una llamada directa desde un subproceso que es diferente del subproceso que creó el objeto receptor será error (como se muestra en los 2 anteriores). Por lo tanto, COM siempre garantiza que los clientes de subprocesos asociados con un STA tengan acceso a este tipo de objeto en un proceso sólo a través de un proxy. Además, estos objetos no deberían agregar con el contador de referencias de subprocesamiento libre ya les permite ejecutarse directamente en subprocesos STA.
  4. Servidor en proceso que admite el modelo de subprocesamiento controlado y el subprocesamiento libre - marcados con ThreadingModel = Both:

    Un objeto proporcionado por este servidor implementa su propia sincronización y acceso de forma simultánea por varios apartamentos del cliente. Además, este objeto se crea y utiliza directamente, en lugar de a través de un proxy en STA o MTA de un proceso de cliente. Puesto que este objeto se utiliza directamente en STA, el servidor debe calcular referencias de interfaces de objetos, posiblemente desde otros servidores, entre subprocesos, por lo que se garantiza el acceso a cualquier objeto de una manera adecuada de subprocesamiento. Además, marcando el modelo de subprocesamiento del objeto como "Both", el implementador del objeto indica lo siguiente: este objeto se puede llamar desde cualquier subproceso del cliente, pero se realizarán las devoluciones de llamada de este objeto al cliente sólo en el apartamento en el que el objeto re el puntero de interfaz al objeto de devolución de llamada recibida. COM permite a este tipo de objeto se cree directamente en un STA, así como en un MTA del proceso del cliente.

    Porque cualquier apartamento que crea este tipo de objeto siempre obtiene un puntero directo en lugar de un puntero de proxy, ThreadingModel "Both" objetos proporcionan mejoras de rendimiento sobre los objetos de ThreadingModel "Libre" cuando carga en STA.

    Porque un ThreadingModel "" objeto también está diseñado para el acceso MTA (es totalmente seguro para subprocesos internamente), pueden acelerar el rendimiento agregando con el contador de referencias proporcionado por CoCreateFreeThreadedMarshaler. Este objeto proporcionado por el sistema se agrega a los objetos llamados y calcula personalizado directos punteros al objeto en todos los apartamentos en el proceso. Clientes en cualquier apartamento, ya sea un STA o MTA, pueden entonces tener acceso el objeto directamente en lugar de a través de un proxy. Por ejemplo, un cliente del modelo STA crea el objeto en un proceso en STA1 y convierte el objeto a STA2. Si el objeto no se agrega con el contador de referencias de subprocesamiento libre, STA2 obtiene acceso al objeto a través de un proxy. Si lo hace, el contador de referencias de subprocesamiento libre proporciona STA2 con un puntero directo al objeto

    Nota: debe tener cuidado al agregar con el contador de referencias de subprocesamiento libre. Como ejemplo, supongamos que un objeto que está marcado como ThreadingModel "Both" (y también agregar con el contador de referencias de subprocesamiento libre) tiene un miembro de datos es un puntero de interfaz a otro objeto cuyo ThreadingModel "Apartamento". A continuación, supongamos que un STA crea el primer objeto y durante la creación, el primer objeto crea el segundo objeto. Según las reglas descritas anteriormente, el primer objeto ahora contiene un puntero directo al segundo objeto. Ahora suponga que el STA calcula las referencias del puntero de interfaz al primer objeto en otro departamento. Porque los primeros agregados de objeto con libre - subproceso contador de referencias, recibe un puntero al primer objeto directo al segundo apartamento. Si el segundo apartamento, a continuación, llama a través de este puntero, y esta llamada hace que el primer objeto llamar a través del puntero de interfaz al segundo objeto, a continuación, ha producido un error, porque el segundo objeto no está diseñado para ser llamado directamente desde el segundo apartamento. Si el primer objeto mantiene un puntero a un proxy para el segundo objeto en lugar de un puntero directo, esto provocará un error diferente. Servidores proxy del sistema también es objetos COM que están asociados con una y solamente una apartamento. Realizar un seguimiento de su apartamento para evitar ciertas circularidades. Por lo que un objeto llamadas en un proxy de un apartamento diferente que el subproceso en el que se ejecuta el objeto recibirá la devolución RPC_E_WRONG_THREAD desde el proxy y se producirá un error en la llamada.

Modelo de interoperabilidad entre clientes y objetos en proceso de subprocesamiento

Se permiten todas las combinaciones de interoperabilidad del modelo de subprocesamiento entre clientes y objetos en proceso.

COM permite a todos los clientes de modelo STA interoperar con objetos de en un proceso de subprocesamiento único creando y obteniendo acceso al objeto en el STA principal del cliente y cálculo de referencias al cliente STA que llamó a CoCreateInstance [Ex].

Si un MTA en un cliente crea un servidor de integrado en un proceso de modelo STA, COM gira "host" STA en el cliente. Este host STA crea el objeto y el puntero de interfaz se calculan referencias de vuelta al MTA. De igual forma, cuando un STA crea un servidor en proceso MTA, COM gira un MTA de host en el que se crea el objeto y atrás cuyas referencias se calculan para la interoperabilidad de STA. entre el modelo de subprocesamiento único y MTA se tratan de forma similar porque el modelo de subprocesamiento único es un degenerado caso del modelo STA.

Debe proporcionar el código de cálculo de referencias para cualquier interfaz personalizada que implementa de un servidor en proceso si desea admitir la interoperabilidad que requiere COM calcular las referencias de la interfaz entre apartamentos del cliente. Consulte la sección referencias a continuación para obtener más información.

Relación entre el modelo de subprocesamiento y devuelve el objeto de generador de clases

Una definición precisa de los servidores en proceso "cargan en" apartamentos se explica en los dos pasos siguientes:

  1. Si el archivo DLL que contiene la clase de servidor en proceso no tiene previamente ha cargado (asignada en el espacio de direcciones de proceso) el cargador del sistema operativo, se realiza la operación y COM Obtiene la dirección de la función DLLGetClassObject exportada por el DLL. Si el archivo DLL se ha cargado previamente por un subproceso asociado con cualquier modelo de subprocesamiento, se omite esta etapa.
  2. COM utiliza el subproceso (o, en el caso de lo MTA, uno de los subprocesos) asociado con el apartamento "Cargando" llamar a la función DllGetClassObject exportada por el DLL pidiendo el CLSID de la clase necesaria. A continuación, se utiliza el objeto factory devuelto para crear instancias de objetos de la clase.

    El segundo paso (la llamada DllGetClassObject por COM) se produce cada vez que un cliente llama a CoGetClassObject/CoCreateIntance [Ex], incluso desde dentro del mismo apartamento. En otras palabras, DllGetClassObject puede denominarse muchas veces por un subproceso asociado con el mismo apartamento; todo depende de cuántos clientes en ese apartamento están intentando obtener acceso a un objeto de fábrica de clase para esa clase.
Autores de implementaciones de la clase y, finalmente, el autor del paquete de un conjunto determinado de clases DLL tienen plena libertad para decidir qué objeto de fábrica para devolver en respuesta a la llamada de la función DllGetClassObject. El autor del paquete DLL tiene la última palabra porque el código "el único punto de entrada toda la DLL DllGetClassObject() detrás" es lo que tiene el derecho de la primera y último potencialmente para decidir qué hacer. Las tres posibilidades típicas son:

  1. DllGetClassObject devuelve un objeto de fábrica de clase única por el subproceso de llamada (lo que significa que un objeto de fábrica de clase por STA y potencialmente varios generadores de clases dentro del MTA).
  2. DllGetClassObject siempre devuelve el mismo objeto de fábrica de la clase, independientemente de la identidad del subproceso que realiza la llamada o el tipo de apartamento asociado con el subproceso de llamada.
  3. DllGetClassObject devuelve un objeto de fábrica de clase única por apartamento llamada (uno por apartamento en STA y MTA).
Existen otras posibilidades para la relación entre las llamadas a DllGetClassObject y objeto generador de clases devuelto realmente (por ejemplo, un nuevo objeto de fábrica de clase por cada llamada a DllGetClassObject) pero no actualmente parecen ser particularmente útil.

Resumen de cliente y el objeto de modelos de subprocesamiento de servidores en proceso

En la tabla siguiente se resume la interacción entre los distintos modelos de subprocesamiento cuando un cliente subproceso primero llama a CoGetClassObject en una clase que se implementa como un servidor en proceso.

Tipos de clientes/subprocesos:

  • cliente se ejecuta en un subproceso asociado con el STA "main" (primer subproceso que llama a CoInitialize o CoInitializeEx con el indicador COINIT_APARTMENTTHREADED)-llamar este STA0 (también denominado modelo de subprocesamiento único -).
  • cliente que ejecuta en un subproceso asociado en cualquier otra llamada STA [ASCII 150] STA *.
  • cliente se ejecuta en un subproceso asociado en el MTA.
Clases de servidores de DLL:

  • Servidor no tiene ninguna clave ThreadingModel--llamar a este "Ninguno".
  • Servidor queda marcado como "Apartamento"--llamar a este "Apt."
  • Servidor queda marcado como "Libre".
  • Servidor queda marcado como "Both".
Al leer la tabla a continuación, mantener en la mente la definición hecha por encima de "cargar" un servidor en un apartamento.

Client Server Result
------ ------ -----------------------------------------
STA0 None Direct access; server loaded into STA0
STA* None Proxy access; server loaded into
STA0.
MTA None Proxy access; server loaded into STA0; STA0 created
automatically by COM if necessary;
STA0 Apt Direct access; server loaded into STA0
STA* Apt Direct access; server loaded into STA*
MTA Apt Proxy access; server loaded into an
STA created automatically by COM.
STA0 Free Proxy access; server is loaded into MTA
MTA created automatically by COM if necessary.
STA* Free Same as STA0->Free
MTA Free Direct access
STA0 Both Direct access; server loaded into STA0
STA* Both Direct access; server loaded into STA*
MTA Both Direct access; server loaded into the MTA

Referencias


Documentación del SDK en la interfaz CoRegisterMessageFilter() y IMessageFilter.

Para obtener información adicional, consulte los artículos siguientes en Microsoft Knowledge Base:
136885 subprocesos OLE deben enviar mensajes
137629 en proc objeto personalizado de interfaz en el cliente del modelo de subprocesamiento controlado