ejercicios - hilos c++
¿Cómo pasar un puntero de interfaz a un hilo? (3)
Básicamente necesitas hacer lo siguiente:
-
CoMashalInterThreadInterfaceInStream
==> obtienes una interfaz IStream. - pasar ese IStream al hilo, por ejemplo, como dijo Quassnoi.
- en SecondaryThread, llame a
CoGetInterfaceAndReleaseStream
para obtener la interfaz (o un proxy, si es necesario).
No libere la interfaz IStream a menos que se cree que falla el hilo, y no salga del hilo hasta que haya llamado a CoGetInterfaceAndReleaseStream
.
El tiempo de ejecución COM creará el proxy automáticamente. El proxy garantiza que, por ejemplo, se llame a un componente COM con subprocesos en el subproceso que lo creó. Sin embargo, esto también requiere que:
- La interfaz es IDispatch, o los componentes proxy / stub están registrados para la interfaz
- el hilo que creó el componente tiene un bucle de mensaje y procesa mensajes
Nota:
- Usando raw Win32 CreateTheard () API
- No MFC
- Una interfaz es simplemente un puntero a un vtable
Pregunta:
- ¿Cómo pasar un puntero de interfaz a un hilo?
Ilustración:
IS8Simulation *pis8 = NULL;
...
CoCreateInstance(
clsid,
NULL,
CLSCTX_LOCAL_SERVER,
__uuidof(IS8Simulation),
(void **) &pis8);
...
hThread = CreateThread(
NULL,
0,
SecondaryThread,
//interface pointer pis8
0,
&dwGenericThreadID);
...
DWORD WINAPI SecondaryThread(LPVOID iValue)
{
//using iValue accordingly
//E.g.: iValue->Open
Saludos
Como se indica a continuación, pasar un puntero de interfaz COM
entre subprocesos no es seguro.
Asumiendo que sabes lo que estás haciendo:
hThread = CreateThread(
NULL,
0,
SecondaryThread,
(LPVOID) pis8
0,
&dwGenericThreadID);
DWORD WINAPI SecondaryThread(LPVOID iValue)
{
((IS8Simulation*) iValue)->Open();
}
Versión segura del hilo:
void MainThread()
{
IStream* psis8;
HRESULT res = CoMarshalInterThreadInterfaceInStream (IID_IS8SIMULATION, pis8, &psis8);
if (FAILED(res))
return;
hThread = CreateThread(
NULL,
0,
SecondaryThread,
(LPVOID) psis8
0,
&dwGenericThreadID
);
}
DWORD WINAPI SecondaryThread(LPVOID iValue)
{
IS8Simulation* pis8;
HRESULT res = CoGetInterfaceAndReleaseStream((IStream*) iValue, IID_IS8SIMULATION, &pis8);
if (FAILED(res))
return (DWORD) res;
pis8->Open();
}
Si la interfaz en su pregunta es una interfaz COM, el enfoque dado por Quassnoi podría no ser suficiente. Debe prestar atención al modelo de subprocesamiento del objeto COM en uso. Si el subproceso secundario se unirá a un apartamento COM distinto del que se creó en su objeto COM, y si ese objeto no es un apartamento ágil , deberá ordenar ese puntero de interfaz para que el subproceso secundario obtenga un proxy, y no es un puntero directo al objeto.
Normalmente, un objeto COM se hace ágil de apartamento utilizando una implementación especial de IMarshal. El enfoque más simple es agregar el Marcador Roscado Libre.
Algunos enlaces útiles ...
Actualización: Acerca del Marshaler de hilo libre ...
Los comentarios sobre este tema dejan claro que algunas personas recomendarían que nunca toque el FTM. Si bien "Effective COM" es un excelente libro, creo que algunas de sus recomendaciones están abiertas a interpretación. El artículo 33 dice "Cuidado con el FTM"; no dice "Nunca use el FTM". Muy sabiamente aconseja precaución particularmente cuando su objeto ágil de apartamento tiene referencias a otros objetos, ya que pueden no ser ágiles. Así que realmente el consejo es: piense detenidamente al construir objetos ágiles en los apartamentos, ya sea que utilicen o no el FTM para lograr su agilidad. Si está seguro de que puede construir un objeto ágil de apartamento, no veo ninguna razón por la cual no usaría el FTM para lograrlo.