Non posso fare a meno di pubblicare questo, anche se non è una risposta diretta alla domanda.
C'è un brillante articolo di MSKB di The Golden Ages of Com: Info: Descrizioni e funzionamento dei modelli di threading ole. Ancora lì e ha tutte le informazioni pertinenti. Il punto è che non dovresti preoccuparti se ci sia il maresciallo o no, se segui le regole. Basta registrare il tuo oggetto come ThreadingModel=Both
, aggrega il maresciatore a filo libero con CoCreateFreeThreadedMarshaler
, e essere fatto. Com farà il marshalling se necessario, nel miglior modo possibile. A seconda del modello di appartamento del cliente, il codice client può ricevere il puntatore diretto all'interfaccia, se segue anche le regole.
Qualsiasi interfaccia "aliena" che potresti ricevere quando viene chiamato un metodo dell'interfaccia, sarà valida nell'ambito della chiamata, perché rimani sulla stessa discussione. Se non hai bisogno di archiviarlo, è tutto ciò che conta.
Se comunque devi memorizzare nella cache l'interfaccia "aliena", il modo giusto di farlo sarebbe quello di archiviarla usando CoMarshalInterThreadInterfaceInStream
/CoGetInterfaceAndReleaseStream
:
Per immagazzinarlo:
- Inserire la sezione critica;
- chiamata
CoMarshalInterThreadInterfaceInStream
e conservare il IStream
puntatore in un campo membro;
- Lasciare la sezione critica;
Per recuperarlo
- Inserire la sezione critica;
- chiamata
CoGetInterfaceAndReleaseStream
Per recuperare l'interfaccia
- chiamata
CoMarshalInterThreadInterfaceInStream
e riporlo di nuovo come IStream
Per qualsiasi uso futuro
- Lasciare la sezione critica;
- Utilizzare l'interfaccia nell'ambito della chiamata corrente
Per rilasciarlo:
- Quando non hai più bisogno di mantenerlo, rilasciare il memorizzazione
IStream
(all'interno della sezione critica).
Se l'oggetto "alieno" è anche a un thread libero e le cose stanno accadendo all'interno dello stesso processo, probabilmente avrai a che fare con un puntatore di interfaccia diretta dopo CoGetInterfaceAndReleaseStream
. Tuttavia, non dovresti fare alcuna ipotesi e non devi davvero sapere se l'oggetto con cui si tratta è l'oggetto originale o un proxy com marshaller.
Questo può essere leggermente ottimizzato utilizzando CoMarshalInterface
con MSHLFLAGS_TABLESTRONG
/ CoUnmarshalInterface
/ IStream::Seek(0, 0)
/ CoReleaseMarshalData
invece di CoGetInterfaceAndReleaseStream
/CoGetInterfaceAndReleaseStream
, per sgrassare la stessa interfaccia quante volte necessario senza rilasciare il flusso.
Sono possibili scenari di memorizzazione nella cache più complessi (e forse più efficienti), coinvolgendo la conservazione locale. Tuttavia, credo che sarebbe un overkill. Non ho fatto alcun tempismo, ma penso che il sovraccarico di CoMarshalInterThreadInterfaceInStream
/CoGetInterfaceAndReleaseStream
è davvero basso.
Detto questo, se hai bisogno di mantenere uno stato che memorizza qualsiasi risorsa o oggetti che potrebbero richiedere affinità del thread, oltre alle interfacce COM di cui sopra, tu non dovrebbe Segna il tuo oggetto come ThreadingModel=Both
o aggregare l'FTM.