2009-02-04 17 views
5

Uwaga:Jak przekazać wskaźnik interfejsu do wątku?

  • Korzystanie surowego Win32 CreateTheard() API
  • Nie MFC
  • interfejs jest po prostu wskaźnik do vtable

Pytanie:

  • Jak przekazać wskaźnik interfejsu do wątku?

Ilustracja:

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 

Pozdrowienia

Odpowiedz

8

Jak wskazano poniżej, przechodzącą wskaźnik COM interfejsu między wątków nie jest bezpieczne.

Zakładając, że wiesz, co robisz:

hThread = CreateThread(
       NULL, 
         0, 
         SecondaryThread, 
         (LPVOID) pis8 
         0, 
         &dwGenericThreadID); 

DWORD WINAPI SecondaryThread(LPVOID iValue) 
{ 
    ((IS8Simulation*) iValue)->Open(); 
} 

wątku bezpieczną wersję:

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(); 
} 
+0

@Quassnoi : Dzięki! – Aaron

+0

Wymaga to interfejsu Marshalling. – Vinay

6

Jeśli interfejs w swoim pytaniu jest interfejs COM, podejście podane przez Quassnoi może nie być wystarczające . Trzeba zwrócić uwagę na model wątkowy używanego obiektu COM. Jeśli wątek dodatkowy zostanie dołączony do oddzielnego mieszkania COM, od tego, w którym został utworzony obiekt COM, i jeśli ten obiekt nie jest apartament-zwinny, musisz wprowadzić ten wskaźnik interfejsu w ten sposób, aby wątek wtórny uzyskał pełnomocnictwo , a nie bezpośredni wskaźnik do obiektu.

Obiekt COM jest zwykle zwinięty w apartament przy użyciu specjalnej implementacji IMarshal. Najprostszym podejściem jest agregowanie Free Threaded Marshaler.

Przydatne linki ...

Aktualizacja: O wolnym gwintowane Marshaler ...

To wynika z komentarzy na ten temat, że niektórzy ludzie by to polecili nigdy nie dotykasz FTM. Chociaż "Effective COM" to doskonała książka, uważam, że niektóre z jej zaleceń są otwarte na interpretację. Punkt 33 mówi "Uważaj na FTM"; nie mówi "Nigdy nie używaj FTM". Bardzo mądrze zaleca się zachować ostrożność, szczególnie gdy twój apartament-obiekt sprawuje odniesienia do innych obiektów, ponieważ mogą one nie być zwinne. Tak naprawdę poradą jest: należy uważnie zastanowić się podczas budowania obiektów zwinnych, niezależnie od tego, czy używają one FTM do osiągnięcia swojej zwinności. Jeśli jesteś pewien, że możesz zbudować obiekt zwinny, nie widzę powodu, dla którego nie używałbyś FTM, aby to osiągnąć.

+0

FTM ma niebezpieczne aspekty (patrz Efektywny COM, pozycja 33, "Uważaj na Free-Threaded Marshaler"). –

+0

GIT jest jednak bardzo użyteczny. –

+0

Tak, nigdy nie używaj FTM ... –

2

Zasadniczo trzeba wykonać następujące czynności:

  • CoMashalInterThreadInterfaceInStream ==> masz interfejs iStream.
  • przekazać IStream do wątku, np. jak powiedział Quassnoi.
  • w SecondaryThread, zadzwoń pod numer CoGetInterfaceAndReleaseStream, aby uzyskać interfejs (lub jego pełnomocnik, jeśli to konieczne).

Nie należy zwalniać interfejsu IStream, chyba że tworzenie wątku zakończy się niepowodzeniem i nie należy opuszczać wątku, dopóki nie zostanie wywołana CoGetInterfaceAndReleaseStream.

Środowisko wykonawcze COM utworzy automatycznie serwer proxy. Proxy zapewnia, że ​​np. Komponent COM z gwintem z mieszkaniem jest wywoływany w wątku, który go utworzył. Wymaga to jednak również, że:

  • Interfejs jest IDispatch lub proxy/stub składniki są zarejestrowane dla interfejsu
  • threadthat stworzył komponent ma pętlę wiadomości i przetwarza wiadomości
+0

Gdzie mogę znaleźć więcej informacji na temat "pętli wiadomości" jest podobna do Win32 API: WaitForSingleObject()? – Aaron

Powiązane problemy