Sdílet prostřednictvím


EventWaitHandle

Třída EventWaitHandle umožňuje, aby vlákna vzájemně komunikují signálem a čekáním na signály. Obslužné rutiny čekání událostí (označované také jako události) jsou obslužné rutiny čekání, které lze signalizovat, aby bylo možné uvolnit jedno nebo více čekajících vláken. Po signálu se obslužná rutina čekání události resetuje buď ručně, nebo automaticky. Třída EventWaitHandle může představovat popisovač čekání místní události (místní událost) nebo pojmenovaný systémový obslužný rutina čekání událostí (pojmenovaná událost nebo systémová událost, viditelná pro všechny procesy).

Poznámka:

Obslužné rutiny čekání událostí nejsou události .NET. Nejsou zapojeni žádní delegáti ani obslužné rutiny událostí. Slovo "event" se používá k popisu, protože byly tradičně označovány jako události operačního systému, a protože akce signalizace obslužného rutiny čekání označuje, že čeká vlákna, že došlo k události.

Místní i pojmenované obslužné rutiny čekání na událost používají objekty synchronizace systému, které jsou chráněné obálkami SafeWaitHandle , aby se zajistilo uvolnění prostředků. Metodu Dispose můžete použít k okamžitému uvolnění prostředků po dokončení použití objektu.

Obslužné rutiny čekání událostí, které se automaticky resetují

Událost automatického resetování vytvoříte zadáním EventResetMode.AutoReset při vytváření objektu EventWaitHandle . Jak už název napovídá, tato synchronizační událost se po uvolnění jednoho čekajícího vlákna automaticky resetuje. Signalizovat událost voláním metody Set .

Události automatického resetování se obvykle používají k poskytování výhradního přístupu k prostředku pro jedno vlákno najednou. Vlákno požaduje prostředek voláním WaitOne metody. Pokud žádné jiné vlákno drží čekání popisovač, metoda vrátí true a volající vlákno má kontrolu nad prostředkem.

Důležité

Stejně jako u všech synchronizačních mechanismů musíte před přístupem k chráněnému prostředku zajistit, aby všechny cesty kódu čekaly na příslušném popisovači čekání. Synchronizace vláken je spolupráce.

Pokud je událost automatického resetování signalována, když nečekají žádná vlákna, zůstane signalována, dokud se vlákno nepokusí čekat na ni. Událost uvolní vlákno a okamžitě resetuje a blokuje další vlákna.

Obslužné rutiny čekání událostí, které se resetují ručně

Událost ručního resetování vytvoříte zadáním EventResetMode.ManualReset při vytváření objektu EventWaitHandle . Jak už název napovídá, tato synchronizační událost musí být po signálu resetována ručně. Dokud se resetuje voláním jeho Reset metody, vlákna, která čekají na popisovač události pokračovat okamžitě bez blokování.

Událost ručního resetování funguje jako brána koryty. Když událost není signalována, vlákna, která na něj čekají, jako koně v korelu. Když je událost signalována voláním své Set metody, všechna čekající vlákna jsou zdarma pokračovat. Událost zůstává signalizovat, dokud se metoda Reset nevolá. Díky tomu je ruční resetování ideální způsob, jak uchovávat vlákna, která musí čekat, dokud jedno vlákno nedokončí úlohu.

Podobně jako koně opouštějící korelní korel, trvá to dlouho, než bude uvolněné vlákna naplánováno operačním systémem a pokračovat v provádění. Reset Pokud je volána metoda před všemi vlákny pokračovat v provádění, zbývající vlákna znovu blokují. Která vlákna obnoví a které vlákna blokují, závisí na náhodných faktorech, jako je zatížení systému, počet vláken čekajících na plánovač atd. To není problém, pokud vlákno, které signalizuje událost končí po signalizaci, což je nejběžnější způsob použití. Pokud chcete, aby vlákno, které signalizovalo událost, zahájilo novou úlohu po obnovení všech čekajících vláken, musíte ho zablokovat, dokud se neobnoví všechna čekající vlákna. V opačném případě máte podmínku časování a chování kódu je nepředvídatelné.

Funkce společné pro automatické a ruční události

Obvykle jeden nebo více vláken blokuje na jednom EventWaitHandle nebo několika vláknech, dokud neblokované vlákno volá Set metodu, která uvolní jedno z čekajících vláken (v případě událostí automatického resetování) nebo všechny z nich (v případě událostí ručního resetování). Vlákno může signalizovat EventWaitHandle a pak ho zablokovat jako atomické operace voláním statické WaitHandle.SignalAndWait metody.

EventWaitHandle objekty lze použít se statickými WaitHandle.WaitAll a WaitHandle.WaitAny metodami. Vzhledem k tomu, že obě EventWaitHandle třídy jsou Mutex odvozeny z WaitHandle, můžete použít obě třídy s těmito metodami.

Pojmenované události

Operační systém Windows umožňuje, aby obslužné rutiny čekání na události měly názvy. Pojmenovaná událost je systémová. To znamená, že po vytvoření pojmenované události je viditelná pro všechna vlákna ve všech procesech. Pojmenované události lze tedy použít k synchronizaci aktivit procesů i vláken.

Pomocí jednoho z konstruktorů, který určuje název události, můžete vytvořit EventWaitHandle objekt představující pojmenovanou systémovou událost.

Poznámka:

Vzhledem k tomu, že pojmenované události jsou v celém systému, je možné mít více EventWaitHandle objektů, které představují stejnou pojmenovanou událost. Pokaždé, když voláte konstruktor nebo metodu OpenExisting , se vytvoří nový EventWaitHandle objekt. Zadáním stejného názvu se opakovaně vytvoří více objektů, které představují stejnou pojmenovanou událost.

Při používání pojmenovaných událostí se doporučuje upozornění. Vzhledem k tomu, že se jedná o systém, může neočekávaně blokovat vaše vlákna jiný proces, který používá stejný název. Škodlivý kód spuštěný na stejném počítači by ho mohl použít jako základ útoku na dostupnost služby.

Zabezpečení řízení přístupu použijte k ochraně objektu EventWaitHandle , který představuje pojmenovanou událost, nejlépe pomocí konstruktoru, který určuje EventWaitHandleSecurity objekt. Zabezpečení řízení přístupu můžete použít také pomocí SetAccessControl této metody, ale v době, kdy se vytvoří obslužná rutina čekání na událost, a časem, kdy je chráněn, ponechá okno ohrožení zabezpečení. Ochrana událostí pomocí zabezpečení řízení přístupu pomáhá zabránit škodlivým útokům, ale nevyřeší problém neúmyslných kolizí názvů.

Poznámka:

EventWaitHandle Na rozdíl od třídy mohou odvozené třídy AutoResetEvent představovat ManualResetEvent pouze místní obslužné rutiny čekání. Nemůžou reprezentovat pojmenované systémové události.

Viz také