Compartir a través de


TN064: Subprocesamiento de modelo apartamento en los controles ActiveX

Nota:

La nota técnica siguiente no se ha actualizado desde que se incluyó por primera vez en la documentación en línea. Como resultado, algunos procedimientos y temas podrían estar obsoletos o ser incorrectos. Para obtener información más reciente, se recomienda buscar el tema de interés en el índice de la documentación en línea.

En esta nota técnica se explica cómo habilitar el subproceso del modelo de apartamento en un control ActiveX. Tenga en cuenta que el subproceso del modelo de apartamento solo se admite en las versiones 4.2 o posteriores de Visual C++.

¿Qué es el subproceso del modelo de apartamento?

El modelo de apartamento es un enfoque para admitir objetos insertados, como controles ActiveX, dentro de una aplicación contenedora multiproceso. Aunque la aplicación puede tener varios subprocesos, cada instancia de un objeto insertado se asignará a un "apartamento" que solo se ejecutará en un subproceso. En otras palabras, todas las llamadas a una instancia de un control se producirán en el mismo subproceso.

Sin embargo, se pueden asignar diferentes instancias del mismo tipo de control a diferentes apartamentos. Por lo tanto, si varias instancias de un control comparten datos en común (por ejemplo, datos estáticos o globales), el acceso a estos datos compartidos deberá estar protegido por un objeto de sincronización, como una sección crítica.

Para obtener información completa sobre el modelo de subprocesos de apartamento, consulte Procesos y subprocesos en la referencia del programador OLE.

¿Por qué admitir el subproceso del modelo de apartamento?

Los controles que admiten el subproceso del modelo de apartamento se pueden usar en aplicaciones contenedoras multiproceso que también admiten el modelo de apartamento. Si no habilita el subproceso del modelo de apartamento, limitará el posible conjunto de contenedores en los que se podría usar el control.

Habilitar el subproceso del modelo de apartamento es fácil para la mayoría de los controles, especialmente si tienen pocos o ningún dato compartido.

Protección de datos compartidos

Si el control usa datos compartidos, como una variable miembro estática, el acceso a esos datos debe protegerse con una sección crítica para evitar que más de un subproceso modifique los datos al mismo tiempo. Para configurar una sección crítica para este fin, declare una variable miembro estática de clase CCriticalSection en la clase del control. Use las funciones miembro Lock y Unlock de este objeto de sección crítico siempre que el código acceda a los datos compartidos.

Considere, por ejemplo, una clase de control que necesita mantener una cadena compartida por todas las instancias. Esta cadena se puede mantener en una variable miembro estática y protegerse mediante una sección crítica. La declaración de clase del control contendrá lo siguiente:

class CSampleCtrl : public COleControl
{
...
    static CString _strShared;
    static CCriticalSection _critSect;
};

La implementación de la clase incluiría definiciones para estas variables:

int CString CSampleCtrl::_strShared;
CCriticalSection CSampleCtrl::_critSect;

A continuación, el acceso al miembro estático _strShared se puede proteger mediante la sección crítica:

void CSampleCtrl::SomeMethod()
{
    _critSect.Lock();
if (_strShared.Empty())
    _strShared = "<text>";
    _critSect.Unlock();

...
}

Registro de un control compatible con el modelo de apartamento

Los controles que admiten el subproceso del modelo de apartamento deben indicar esta funcionalidad en el registro agregando el valor con nombre "ThreadingModel" con un valor de "Apartment" en su entrada del registro del identificador de clase en la clave class id\InprocServer32. Para que esta clave se registre automáticamente para el control, pase la marca afxRegApartmentThreading del sexto parámetro a AfxOleRegisterControlClass:

BOOL CSampleCtrl::CSampleCtrlFactory::UpdateRegistry(BOOL bRegister)
{
    if (bRegister)
    return AfxOleRegisterControlClass(
    AfxGetInstanceHandle(),
    m_clsid,
    m_lpszProgID,
    IDS_SAMPLE,
    IDB_SAMPLE,
    afxRegApartmentThreading,
    _dwSampleOleMisc,
    _tlid,
    _wVerMajor,
    _wVerMinor);

else
    return AfxOleUnregisterClass(m_clsid,
    m_lpszProgID);

}

Si controlWizard generó el proyecto de control en Visual C++ versión 4.1 o posterior, esta marca ya estará presente en el código. No es necesario realizar ningún cambio para registrar el modelo de subproceso.

Si el proyecto lo generó una versión anterior de ControlWizard, el código existente tendrá un valor booleano como el sexto parámetro. Si el parámetro existente es TRUE, cámbielo a afxRegInsertable | afxRegApartmentThreading. Si el parámetro existente es FALSE, cámbielo a afxRegApartmentThreading.

Si el control no sigue las reglas del subproceso del modelo de apartamento, no debe pasar afxRegApartmentThreading en este parámetro.

Consulte también

Notas técnicas por número
Notas técnicas por categoría