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.
La EventWaitHandle classe consente ai thread di comunicare tra loro segnalando e aspettando i segnali. Gli handle di attesa degli eventi (detti semplicemente eventi) sono handle di attesa che possono essere segnalate per rilasciare uno o più thread in attesa. Dopo la segnalazione, un handle di attesa dell'evento viene reimpostato manualmente o automaticamente. La classe EventWaitHandle può rappresentare un gestore di attesa degli eventi locale (evento locale) oppure un gestore di attesa per eventi di sistema denominato (evento denominato o evento di sistema, visibile a tutti i processi).
Annotazioni
Gli handle di attesa degli eventi non sono eventi .NET. Non sono coinvolti delegati o gestori eventi. La parola "event" viene usata per descriverli perché tradizionalmente sono stati definiti eventi del sistema operativo e perché l'atto di notificare l'handle di attesa indica ai thread che stanno aspettando che si è verificato un evento.
Gli handle di attesa degli eventi locali e denominati usano oggetti di sincronizzazione del sistema, protetti da SafeWaitHandle wrapper per assicurarsi che le risorse vengano rilasciate. È possibile usare il Dispose metodo per liberare immediatamente le risorse al termine dell'utilizzo dell'oggetto .
Segnali di attesa eventi che si reimpostano automaticamente
Si crea un evento di reimpostazione automatica specificando EventResetMode.AutoReset quando si crea l'oggetto EventWaitHandle . Come suggerisce il nome, questo evento di sincronizzazione viene reimpostato automaticamente quando viene segnalato, dopo il rilascio di un singolo thread in attesa. Segnalare l'evento chiamando il relativo Set metodo.
Gli eventi di reimpostazione automatica vengono in genere usati per fornire l'accesso esclusivo a una risorsa per un singolo thread alla volta. Un thread richiede la risorsa chiamando il WaitOne metodo . Se nessun altro thread contiene l'handle di attesa, il metodo restituisce true e il thread chiamante ha il controllo della risorsa.
Importante
Come per tutti i meccanismi di sincronizzazione, è necessario assicurarsi che tutti i percorsi di codice attendino l'handle di attesa appropriato prima di accedere a una risorsa protetta. La sincronizzazione dei thread è cooperativa.
Se viene segnalato un evento di reimpostazione automatica quando non è in attesa alcun thread, rimane segnalato fino a quando un thread non tenta di attenderlo. L'evento libera il thread e si resetta immediatamente, bloccando i thread successivi.
Handler di attesa eventi che si reimpostano manualmente
Si crea un evento di reimpostazione manuale specificando EventResetMode.ManualReset quando si crea l'oggetto EventWaitHandle . Come suggerisce il nome, questo evento di sincronizzazione deve essere reimpostato manualmente dopo che è stato segnalato. Fino a quando non viene reimpostato il relativo metodo Reset, i thread che attendono l'handle dell'evento procedono immediatamente senza bloccare.
Un evento di ripristino manuale funziona come il cancello di un recinto. Quando l'evento non viene segnalato, i thread che attendono su di esso rimangono bloccati, come cavalli in un recinto. Quando l'evento viene segnalato, chiamando il relativo Set metodo, tutti i thread in attesa sono liberi di procedere. L'evento rimane segnalato fino a quando non viene chiamato il relativo Reset metodo. In questo modo l'evento di reimpostazione manuale è un modo ideale per sospendere i thread che devono attendere fino a quando un thread finisca un'attività.
Come i cavalli che lasciano un recinto, i thread rilasciati impiegano tempo per essere pianificati dal sistema operativo e riprendere l'esecuzione. Se il metodo Reset viene chiamato prima che tutti i thread abbiano ripreso l'esecuzione, i thread rimanenti saranno ancora una volta bloccati. I thread che riprendono e quelli che si bloccano dipendono da fattori casuali come il carico sul sistema, il numero di thread in attesa del scheduler, e altri simili. Questo non è un problema se il thread che segnala l'evento termina subito dopo averlo fatto, poiché questo è il modello di utilizzo più comune. Se si vuole che il thread che ha segnalato l'evento inizi una nuova attività dopo che tutti i thread in attesa sono stati ripresi, è necessario bloccarlo fino a quando non vengono ripresi tutti i thread in attesa. Altrimenti, si ha una condizione di competizione e il comportamento del codice è imprevedibile.
Funzionalità comuni agli eventi automatici e manuali
In genere, uno o più thread si bloccano su un EventWaitHandle finché un thread sbloccato non chiama il metodo Set, che rilascia uno dei thread in attesa nel caso di eventi di reimpostazione automatica, oppure tutti nel caso di eventi di reimpostazione manuale. Un thread può segnalare un oggetto EventWaitHandle e quindi bloccarlo, come operazione atomica, chiamando il metodo statico WaitHandle.SignalAndWait .
EventWaitHandlegli oggetti possono essere usati con i metodi statici WaitHandle.WaitAll e WaitHandle.WaitAny. Poiché le EventWaitHandle classi e Mutex derivano entrambe da WaitHandle, è possibile usare entrambe le classi con questi metodi.
Eventi denominati
Il sistema operativo Windows consente agli handle di attesa degli eventi di avere nomi. Un evento denominato è interno al sistema. Ovvero, una volta creato l'evento denominato, è visibile a tutti i thread in tutti i processi. Pertanto, gli eventi denominati possono essere usati per sincronizzare le attività dei processi e i thread.
È possibile creare un EventWaitHandle oggetto che rappresenta un evento di sistema denominato utilizzando uno dei costruttori che specifica un nome di evento.
Annotazioni
Poiché gli eventi denominati sono a livello di sistema, è possibile avere più EventWaitHandle oggetti che rappresentano lo stesso evento denominato. Ogni volta che si chiama un costruttore o il OpenExisting metodo , viene creato un nuovo EventWaitHandle oggetto . Se si specifica ripetutamente lo stesso nome, vengono creati più oggetti che rappresentano lo stesso evento denominato.
Si consiglia di usare cautela nell'uso degli eventi con nome. Poiché sono a livello di sistema, un altro processo che usa lo stesso nome può bloccare i thread in modo imprevisto. Il codice dannoso in esecuzione nello stesso computer potrebbe usarlo come base di un attacco Denial of Service.
Utilizzare la sicurezza del controllo di accesso per proteggere un EventWaitHandle oggetto che rappresenta un evento denominato, preferibilmente usando un costruttore che specifica un EventWaitHandleSecurity oggetto . È anche possibile applicare la sicurezza del controllo di accesso usando il SetAccessControl metodo , ma lascia una finestra di vulnerabilità tra il momento in cui viene creato l'handle di attesa dell'evento e l'ora in cui è protetta. La protezione degli eventi con la sicurezza del controllo di accesso consente di prevenire attacchi dannosi, ma non risolve il problema di conflitti di nomi non intenzionali.
Annotazioni
A differenza della EventWaitHandle classe , le classi AutoResetEvent derivate e ManualResetEvent possono rappresentare solo handle di attesa locali. Non possono rappresentare eventi di sistema denominati.