Appartamenti multithreading

In un modello apartment multithreading, tutti i thread nel processo inizializzati come thread liberi risiedono in un singolo apartment. Non è quindi necessario effettuare il marshalling tra thread. I thread non devono recuperare e inviare messaggi perché COM non usa messaggi finestra in questo modello.

Le chiamate ai metodi degli oggetti nell'apartment multithreading possono essere eseguite su qualsiasi thread nell'apartment. Non esiste alcuna serializzazione delle chiamate; molte chiamate possono verificarsi contemporaneamente allo stesso metodo o allo stesso oggetto. Gli oggetti creati nell'apartment multithreading devono essere in grado di gestire le chiamate sui relativi metodi da altri thread in qualsiasi momento.

Poiché le chiamate agli oggetti non vengono serializzate in alcun modo, la concorrenza di oggetti multithreading offre le prestazioni più elevate e sfrutta al meglio l'hardware multiprocessore per chiamate tra thread, cross-process e tra computer. Ciò significa, tuttavia, che il codice per gli oggetti deve fornire la sincronizzazione nelle implementazioni dell'interfaccia, in genere tramite l'uso di primitive di sincronizzazione, ad esempio oggetti evento, sezioni critiche, mutex o semafori, descritti più avanti in questa sezione. Inoltre, poiché l'oggetto non controlla la durata dei thread che vi accedono, non è possibile archiviare alcuno stato specifico del thread nell'oggetto (nell'archiviazione locale del thread).

Di seguito sono riportate alcune considerazioni importanti relative alla sincronizzazione per gli appartamenti multithreading:

  • COM fornisce la sincronizzazione delle chiamate solo per appartamenti a thread singolo.
  • Gli appartamenti multithreading non ricevono chiamate durante l'esecuzione di chiamate (sullo stesso thread).
  • Gli appartamenti multithreading non possono effettuare chiamate sincronizzate con input.
  • Le chiamate asincrone vengono convertite in chiamate sincrone in appartamenti multithreading.
  • Il filtro dei messaggi non viene chiamato per alcun thread in un apartment multithreading.

Per inizializzare un thread come thread libero, chiamare CoInitializeEx, specificando COINIT_MULTITHREADED. Per informazioni sul threading del server in-process, vedere Problemi di threading del server in-process.

Più client possono chiamare simultaneamente, da thread diversi, un oggetto che supporta il threading libero. Nei server out-of-process senza thread, COM, tramite il sottosistema RPC, crea un pool di thread nel processo server e una chiamata client (o più chiamate client) può essere recapitata da uno di questi thread in qualsiasi momento. Un server out-of-process deve implementare anche la sincronizzazione nella class factory. Gli oggetti in-process senza thread possono ricevere chiamate dirette da più thread del client.

Il client può eseguire operazioni COM in più thread. Tutti i thread appartengono allo stesso apartment multithreading. I puntatori di interfaccia vengono passati direttamente dal thread al thread all'interno di un apartment multithreading, quindi i puntatori di interfaccia non vengono sottoposto a marshalling tra i thread. I filtri dei messaggi (implementazioni di IMessageFilter) non vengono usati in appartamenti multithreading. Il thread client verrà sospeso quando effettua una chiamata COM a oggetti out-of-apartment e riprenderà al termine della chiamata. Le chiamate tra processi vengono comunque gestite da RPC.

I thread inizializzati con il modello a thread libero devono implementare la propria sincronizzazione. Come accennato in precedenza in questa sezione, Windows abilita questa implementazione tramite le primitive di sincronizzazione seguenti:

  • Gli oggetti evento forniscono un modo per segnalare uno o più thread che si sono verificati eventi. Qualsiasi thread all'interno di un processo può creare un oggetto evento. Un handle per l'evento viene restituito dalla funzione di creazione di eventi CreateEvent. Dopo aver creato un oggetto evento, i thread con un handle per l'oggetto possono attendere prima di continuare l'esecuzione.
  • Le sezioni critiche vengono usate per una sezione di codice che richiede l'accesso esclusivo a un set di dati condivisi prima che possa essere eseguito e usato solo dai thread all'interno di un singolo processo. Una sezione critica è come una turnstile attraverso la quale può passare un solo thread alla volta, funzionando come segue:
    • Per garantire che non più di un thread alla volta accesa ai dati condivisi, il thread primario di un processo alloca una struttura di dati CRITICAL_edizione Standard CTION globale e inizializza i relativi membri. Un thread che immette una sezione critica chiama la funzione EnterCriticalSection e modifica i membri della struttura dei dati.
    • Un thread che tenta di immettere una sezione critica chiama EnterCriticalSection che verifica se la struttura dei dati CRITICAL_edizione Standard CTION è stata modificata. In tal caso, un altro thread è attualmente presente nella sezione critica e il thread successivo viene messo in sospensione. Un thread che lascia una sezione critica chiama LeaveCriticalSection, che reimposta la struttura dei dati. Quando un thread lascia una sezione critica, il sistema riattiva uno dei thread in sospensione, che quindi entra nella sezione critica.
  • I mutex eseguono la stessa funzione di una sezione critica, ad eccezione del fatto che il mutex è accessibile ai thread in esecuzione in processi diversi. Possedere un oggetto mutex è come avere il pavimento in un dibattito. Un processo crea un oggetto mutex chiamando la funzione CreateMutex , che restituisce un handle. Il primo thread che richiede un oggetto mutex ottiene la proprietà di esso. Al termine del thread con il mutex, la proprietà passa ad altri thread in base al primo servizio.
  • I semafori vengono usati per mantenere un conteggio dei riferimenti per alcune risorse disponibili. Un thread crea un semaforo per una risorsa chiamando la funzione CreateSemaphore e passando un puntatore alla risorsa, un numero di risorse iniziale e il numero massimo di risorse. Questa funzione restituisce un handle. Un thread che richiede una risorsa passa il relativo handle semaforo in una chiamata alla funzione WaitForSingleObject. L'oggetto semaforo esegue il polling della risorsa per determinare se è disponibile. In tal caso, il semaforo decrementa il conteggio delle risorse e riattiva il thread in attesa. Se il conteggio è zero, il thread rimane in stato di sospensione fino a quando un altro thread rilascia una risorsa, causando l'incremento del semaforo a uno.

Accesso alle interfacce tra appartamenti

Scelta del modello di threading

Problemi di threading del server in-process

Processi, thread e appartamenti

Comunicazione a thread singolo e multithreading

Appartamenti a thread singolo