Contesti
Questo documento descrive il ruolo dei contesti nel runtime di concorrenza. Un thread collegato a un'utilità di pianificazione è noto come contesto di esecuzione o solo contesto. La funzione concurrency::wait e la classe concurrency::Context consentono di controllare il comportamento dei contesti. Usare la wait
funzione per sospendere il contesto corrente per un'ora specificata. Usare la Context
classe quando è necessario un maggiore controllo su quando i contesti bloccano, sbloccano e producono o quando si desidera sovrascrivere il contesto corrente.
Suggerimento
Il runtime di concorrenza fornisce un'utilità di pianificazione predefinita, pertanto non è necessario crearne una nell'applicazione. Poiché l'Utilità di pianificazione consente di ottimizzare le prestazioni delle applicazioni, è consigliabile iniziare con la libreria PPL (Parallel Patterns Library) o la libreria degli agenti asincroni se non si ha una novità del runtime di concorrenza.
Funzione wait
La funzione concurrency::wait restituisce in modo cooperativo l'esecuzione del contesto corrente per un numero specificato di millisecondi. Il runtime usa il tempo di resa per eseguire altre attività. Dopo che è trascorso il tempo specificato, il runtime riprogramma il contesto per l'esecuzione. Pertanto, la wait
funzione potrebbe sospendere il contesto corrente più a lungo del valore fornito per il milliseconds
parametro.
Il passaggio di 0 (zero) per il milliseconds
parametro fa sì che il runtime sospende il contesto corrente fino a quando non viene data la possibilità di eseguire il lavoro in tutti gli altri contesti attivi. In questo modo è possibile restituire un'attività a tutte le altre attività attive.
Esempio
Per un esempio che usa la wait
funzione per restituire il contesto corrente e consentire l'esecuzione di altri contesti, vedere Procedura: Usare i gruppi di pianificazione per influenzare l'ordine di esecuzione.
Classe Context
La classe concurrency::Context fornisce un'astrazione di programmazione per un contesto di esecuzione e offre due funzionalità importanti: la possibilità di bloccare in modo cooperativo, sbloccare e restituire il contesto corrente e la possibilità di sovrascrivere il contesto corrente.
Blocco cooperativo
La Context
classe consente di bloccare o restituire il contesto di esecuzione corrente. Il blocco o la resa è utile quando il contesto corrente non può continuare perché una risorsa non è disponibile.
Il metodo concurrency::Context::Block blocca il contesto corrente. Un contesto bloccato restituisce le risorse di elaborazione in modo che il runtime possa eseguire altre attività. Il metodo concurrency::Context::Unblock sblocca un contesto bloccato. Il Context::Unblock
metodo deve essere chiamato da un contesto diverso da quello che ha chiamato Context::Block
. Il runtime genera un'eccezione concurrency::context_self_unblock se un contesto tenta di sbloccare se stesso.
Per bloccare e sbloccare in modo cooperativo un contesto, in genere si chiama concurrency::Context::CurrentContext per recuperare un puntatore all'oggetto Context
associato al thread corrente e salvare il risultato. Chiamare quindi il Context::Block
metodo per bloccare il contesto corrente. Successivamente, chiamare Context::Unblock
da un contesto separato per sbloccare il contesto bloccato.
È necessario associare ogni coppia di chiamate a Context::Block
e Context::Unblock
. Il runtime genera concurrency::context_unblock_unbalanced quando il Context::Block
metodo o Context::Unblock
viene chiamato consecutivamente senza una chiamata corrispondente all'altro metodo. Tuttavia, non è necessario chiamare Context::Block
prima di chiamare Context::Unblock
. Ad esempio, se un contesto chiama prima che un altro contesto chiami Context::Unblock
Context::Block
lo stesso contesto, tale contesto rimane sbloccato.
Il metodo concurrency::Context::Yield restituisce l'esecuzione in modo che il runtime possa eseguire altre attività e quindi riprogrammare il contesto per l'esecuzione. Quando si chiama il Context::Block
metodo , il runtime non riprogramma il contesto.
Esempio
Per un esempio che usa i Context::Block
metodi , Context::Unblock
e Context::Yield
per implementare una classe semaforo cooperativo, vedere Procedura: Usare la classe Context per implementare un semaforo cooperativo.
Oversubscription
L'utilità di pianificazione predefinita crea lo stesso numero di thread disponibili. È possibile usare l'oversubscription per creare thread aggiuntivi per un determinato thread hardware.
Per le operazioni a elevato utilizzo di calcolo, l'oversubscription in genere non viene ridimensionato perché comporta un sovraccarico aggiuntivo. Tuttavia, per le attività con una quantità elevata di latenza, ad esempio la lettura dei dati dal disco o da una connessione di rete, l'oversubscription può migliorare l'efficienza complessiva di alcune applicazioni.
Nota
Abilitare l'oversubscription solo da un thread creato dal runtime di concorrenza. L'oversubscription non ha alcun effetto quando viene chiamato da un thread che non è stato creato dal runtime (incluso il thread principale).
Per abilitare l'oversubscription nel contesto corrente, chiamare il metodo concurrency::Context::Oversubscribe con il _BeginOversubscription
parametro impostato su true
. Quando si abilita l'oversubscription in un thread creato dal runtime di concorrenza, il runtime crea un thread aggiuntivo. Al termine di tutte le attività che richiedono l'oversubscription, chiamare Context::Oversubscribe
con il _BeginOversubscription
parametro impostato su false
.
È possibile abilitare l'oversubscription più volte dal contesto corrente, ma è necessario disabilitarlo lo stesso numero di volte in cui viene abilitato. L'oversubscription può anche essere annidato; vale a dire, un'attività creata da un'altra attività che usa oversubscription può anche sovrascrivere il contesto. Tuttavia, se un'attività nidificata e il relativo elemento padre appartengono allo stesso contesto, solo la chiamata più esterna a Context::Oversubscribe
causa della creazione di un thread aggiuntivo.
Nota
Il runtime genera concurrency::invalid_oversubscribe_operation se l'oversubscription è disabilitato prima dell'abilitazione.
Esempio
Per un esempio che usa l'oversubscription per compensare la latenza causata dalla lettura dei dati da una connessione di rete, vedere Procedura: Usare oversubscription per compensare la latenza.
Vedi anche
Utilità di pianificazione
Procedura: Usare i gruppi di pianificazione per influenzare l'ordine di esecuzione
Procedura: Usare la classe Context per implementare una classe semaforo di cooperazione
Procedura: Usare l'oversubscription per compensare la latenza