2009-02-04 17 views
5

Nota:Come passare un puntatore a un'interfaccia?

  • Utilizzando prime Win32 CreateTheard() API
  • No MFC
  • Un'interfaccia è semplicemente un puntatore ad una vtable

Domanda:

  • Come passare un puntatore a un'interfaccia?

Illustrazione:

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 

saluti

risposta

8

Come rilevato sotto, passando un puntatore COM interfaccia tra i thread in non sicuro.

Supponendo che si sa cosa si sta facendo:

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

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

Discussione versione sicura:

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 : Grazie! – Aaron

+0

Ciò richiede il marshalling dell'interfaccia. – Vinay

6

Se l'interfaccia in questione è un interfaccia COM, l'approccio data dal Quassnoi potrebbe non essere sufficiente . È necessario prestare attenzione al modello di thread dell'oggetto COM in uso. Se il thread secondario entrerà a far parte di un appartamento COM separato da quello in cui è stato creato l'oggetto COM e se tale oggetto non è apartment-agile, sarà necessario eseguire il marshalling di tale puntatore dell'interfaccia in modo che il thread secondario riceva un proxy e non un puntatore diretto all'oggetto.

Un oggetto COM viene normalmente reso appartamento-agile utilizzando un'implementazione speciale di IMarshal. L'approccio più semplice è quello di aggregare il Marshaler con thread libero.

Alcuni link utili ...

Aggiornamento: A proposito del Free-Threaded Marshaler ...

E 'chiaro dai commenti su questo argomento che alcune persone lo raccomanderebbero non tocchi mai l'FTM. Mentre "Effective COM" è un libro eccellente, penso che alcune delle sue raccomandazioni siano aperte all'interpretazione. L'articolo 33 dice "Attenti all'FTM"; non dice "Non usare mai l'FTM". Molto saggiamente consiglia cautela in particolare quando il tuo oggetto appartamento-agile detiene riferimenti ad altri oggetti, perché potrebbero non essere appartamento-agile. Quindi il consiglio è davvero: pensare attentamente quando si costruiscono oggetti agili, se usano o meno l'FTM per ottenere la loro agilità. Se sei sicuro di poter costruire un oggetto appartamento-agile, non vedo alcun motivo per non utilizzare l'FTM per raggiungere questo obiettivo.

+0

FTM presenta aspetti pericolosi (vedere la COM efficace, elemento 33, "Attenzione al Marshaler a thread libero") –

+0

Il GIT è molto utile. –

+0

Sì, non usare mai FTM ... –

2

È fondamentalmente bisogno di fare quanto segue:

  • CoMashalInterThreadInterfaceInStream ==> si ottiene un interfaccia IStream.
  • passa l'IStream alla discussione, ad es. come diceva Quassnoi.
  • in SecondaryThread, chiamare CoGetInterfaceAndReleaseStream per ottenere l'interfaccia (o un proxy, se necessario).

Non rilasciare l'interfaccia IStream a meno che la creazione del thread non riesca e non uscire dal thread finché non si chiama CoGetInterfaceAndReleaseStream.

Il runtime COM creerà automaticamente il proxy. Il proxy garantisce che ad es. un componente COM thread apartment viene chiamato sul thread che lo ha creato. Tuttavia, questo richiede anche che:

  • L'interfaccia è IDispatch, o un proxy/stub componenti sono registrati per l'interfaccia
  • il threadthat creato il componente ha un ciclo di messaggi e elabora i messaggi
+0

Dove posso trovare ulteriori informazioni su un "loop di messaggi" è simile all'API Win32: WaitForSingleObject()? – Aaron

Problemi correlati