Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Un processo è una raccolta di risorse di memoria virtuale, codice, dati e sistema. Un thread è codice che deve essere eseguito serialmente all'interno di un processo. Un processore esegue thread, non processi, quindi ogni applicazione ha almeno un processo e un processo ha sempre almeno un thread di esecuzione, noto come thread primario. Un processo può avere più thread oltre al thread primario.
I processi comunicano tra loro tramite messaggi, usando la tecnologia RPC (Remote Procedure Call) di Microsoft per passare le informazioni l'una all'altra. Non esiste alcuna differenza per il chiamante tra una chiamata proveniente da un processo in un computer remoto e una chiamata proveniente da un altro processo nello stesso computer.
Quando un thread inizia a essere eseguito, continua fino a quando non viene terminato o finché non viene interrotto da un thread con priorità più alta (da un'azione dell'utente o dall'utilità di pianificazione del thread del kernel). Ogni thread può eseguire sezioni separate di codice o più thread possono eseguire la stessa sezione di codice. I thread che eseguono lo stesso blocco di codice mantengono stack separati. Ogni thread in un processo condivide le variabili e le risorse globali del processo.
L'utilità di pianificazione del thread determina quando e con quale frequenza eseguire un thread, in base a una combinazione dell'attributo della classe di priorità del processo e della priorità di base del thread. Per impostare l'attributo della classe di priorità di un processo, chiamare la funzione SetPriorityClass e impostare la priorità di base di un thread con una chiamata a SetThreadPriority.
Le applicazioni multithread devono evitare due problemi di concorrenza tra thread: deadlock e race condition. Si verifica un deadlock quando ciascun thread è in attesa che l'altro faccia qualcosa. Il controllo chiamate COM consente di evitare deadlock nelle chiamate tra oggetti. Una condizione di race si verifica quando un thread termina prima di un altro da cui dipende, inducendo il primo a utilizzare un valore non inizializzato perché il secondo non ne ha ancora fornito uno valido. COM fornisce alcune funzioni appositamente progettate per evitare condizioni di competizione nei server esterni al processo. (Vedere Utilità di supporto per l'implementazione del server fuori processo.)
L'apartment e l'architettura del threading COM
Mentre COM supporta il modello a thread singolo per processo prevalente prima dell'introduzione di più thread di esecuzione, è possibile scrivere codice per sfruttare i vantaggi di più thread, ottenendo applicazioni più efficienti, consentendo l'esecuzione di un thread mentre un altro thread attende il completamento di un'operazione dispendiosa in termini di tempo.
Nota
L'uso di più thread non garantisce prestazioni migliori. Infatti, poiché il factoring del thread è un problema difficile, l'uso di più thread spesso causa problemi di prestazioni. La chiave consiste nell'usare più thread solo se si è certi di ciò che si sta facendo.
In generale, il modo più semplice per visualizzare l'architettura di threading COM consiste nel considerare tutti gli oggetti COM nel processo come divisi in gruppi chiamati appartamenti . Un oggetto COM vive esattamente in un appartamento, nel senso che i suoi metodi possono essere chiamati direttamente solo da un thread che appartiene a quell'appartamento. Qualsiasi altro thread che vuole chiamare l'oggetto deve passare attraverso un proxy.
Ci sono due tipi di appartamenti: appartamenti a thread singolo e appartamenti multithread.
Importante
Scelta di un modello di appartamento (STA vs MTA):
| Appartamento |
CoInitializeEx Bandiera |
Usa quando |
|---|---|---|
| STA (a thread singolo) | COINIT_APARTMENTTHREADED |
Il thread ha un ciclo di messaggi (thread dell'interfaccia utente) oppure si usano oggetti COM che richiedono una pompa dei messaggi (controlli ActiveX, oggetti Shell, trascinamento della selezione). |
| MTA (multithread) | COINIT_MULTITHREADED |
Il thread esegue operazioni in background senza ciclo di messaggi e gli oggetti COM usati sono thread-safe o agile. |
Errore comune che porta al deadlock: Un thread STA deve elaborare i messaggi (tramite GetMessage/DispatchMessage o equivalente). Se un thread STA si blocca su una primitiva di sincronizzazione (ad esempio WaitForSingleObject) senza elaborare i messaggi, le chiamate COM in ingresso agli oggetti in quell'appartamento non verranno mai inoltrate, provocando deadlock. Usare CoWaitForMultipleHandles o MsgWaitForMultipleObjects invece di attese non elaborate in un thread STA.
- Gli appartamenti a thread singolo sono costituiti da un solo thread, quindi tutti gli oggetti COM che risiedono in un apartment a thread singolo possono ricevere chiamate di metodo solo dal thread che appartiene a tale apartment. Tutte le chiamate di metodo verso un oggetto COM in un apartment a thread singolo vengono sincronizzate con la coda di messaggi di Windows per il thread dell'apartment a thread singolo. Un processo con un singolo thread di esecuzione è semplicemente un caso speciale di questo modello.
- Gli appartamenti multithreading sono costituiti da uno o più thread, quindi tutti gli oggetti COM che vivono in un apartment multithreading possono ricevere chiamate di metodo direttamente da qualsiasi thread appartenente all'apartment multithreading. I thread in un apartment multithread utilizzano un modello chiamato free-threading. Le chiamate agli oggetti COM in un multithreaded apartment vengono sincronizzate dagli oggetti stessi.
Nota
Per una descrizione della comunicazione tra apartment a thread singolo e apartment multithread nello stesso processo, vedere Comunicazione tra apartment a thread singolo e apartment multithread.
Un processo può avere zero o più appartamenti a thread singolo e zero o un appartamento multithreading.
In un processo, l'appartamento principale è il primo a essere inizializzato. In un processo a thread singolo, questo è l'unico appartamento. I parametri di chiamata vengono sottoposti a marshalling tra appartamenti e COM gestisce la sincronizzazione tramite messaggistica. Se si designano più thread in un processo per essere a thread libero, tutti i thread liberi risiedono in un singolo apartment, i parametri vengono passati direttamente a qualsiasi thread nell'apartment ed è necessario gestire tutta la sincronizzazione. In un processo con threading libero e threading apartment, tutti i thread liberi risiedono in un unico appartamento e tutti gli altri appartamenti sono appartamenti a thread singolo. Un processo che esegue operazioni COM è un insieme di appartamenti con, al massimo, un appartamento multithread, ma un numero qualsiasi di appartamenti a thread singolo.
I modelli di threading in COM forniscono il meccanismo per client e server che usano architetture di threading diverse per collaborare. Le chiamate tra oggetti con modelli di threading diversi in processi diversi sono naturalmente supportate. Dal punto di vista dell'oggetto chiamante, tutte le chiamate agli oggetti all'esterno di un processo si comportano in modo identico, indipendentemente dalla modalità di threading dell'oggetto chiamato. Analogamente, dal punto di vista dell'oggetto chiamato, le chiamate in arrivo si comportano in modo identico, indipendentemente dal modello di threading del chiamante.
L'interazione tra un client e un oggetto out-of-process è semplice, anche quando usano modelli di threading diversi perché il client e l'oggetto si trovano in processi diversi. COM, interposto tra il client e il server, può fornire il codice per consentire l'interoperabilità tra i modelli di threading, utilizzando il marshaling standard e RPC. Ad esempio, se un oggetto a thread singolo viene chiamato simultaneamente da più client a thread libero, le chiamate verranno sincronizzate da COM inserendo i messaggi di finestra corrispondenti nella coda dei messaggi del server. L'appartamento dell'oggetto riceverà una chiamata ogni volta che recupera e invia messaggi. Tuttavia, è necessario prestare attenzione per garantire che i server in-process interagiscono correttamente con i client. (Vedere Problemi di threading del server In-Process.)
Il problema più importante nella programmazione con un modello multithreading consiste nel rendere thread-safe il codice in modo che i messaggi destinati a un determinato thread vadano solo a quel thread e l'accesso ai thread sia protetto.
Per altre informazioni, vedere gli argomenti seguenti:
- Scelta del modello di threading
- Appartamenti a thread singolo
- appartamenti multithreading
- Comunicazione a thread singolo e multithread
- Problemi di threading del server in-process
- Accesso alle interfacce tra gli appartamenti