Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Třída EventWaitHandle umožňuje, aby vlákna vzájemně komunikují signálem a čekáním na signály. Čekací rutiny událostí (označované také jako události) jsou čekací rutiny, které lze signalizovat, aby bylo možné uvolnit jedno nebo více čekajících vláken. Po vyvolání se čekací úchyt události resetuje buď ručně, nebo automaticky. Třída EventWaitHandle může představovat buď popisovač čekání místní události (místní událost), nebo pojmenovaný popisovač čekání systémové události (pojmenovaná událost nebo systémová událost, viditelná pro všechny procesy).
Poznámka:
Nástroje pro čekání na události nejsou události .NET. Nejsou zapojeni žádní delegáti ani obslužné rutiny událostí. Slovo "event" se používá k jejich popisu, protože byly tradičně označovány jako události operačního systému, a protože signalizace čekacího objektu naznačuje čekajícím vláknům, ž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 při signalizaci automaticky resetuje po uvolnění jednoho čekajícího vlákna. 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 metody WaitOne. Pokud žádné jiné vlákno nedrží čekací 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 kooperativní.
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.
Manipulátory č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á, událost synchronizace musí být po signalizaci resetována ručně. Dokud není resetována voláním jeho metody Reset, vlákna, která čekají na popisovač události, pokračují okamžitě, aniž by byla blokována.
Událost ručního resetování funguje jako brána ohrady. Když událost není signalizována, vlákna, která na jej čekají, blokují jako koně v ohradě. Když je událost signalována voláním jeho Set metody, mohou všechna čekající vlákna pokračovat. Událost zůstává signalizována, dokud není metoda Reset zavolána. 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í ohradu, trvá nějaký čas, než operační systém naplánuje uvolněná vlákna a pokračuje v jejich provádění. Pokud je metoda Reset volána před tím, než všechna vlákna pokračují v provádění, zbývající vlákna se opět zablokují. 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 problém s podmínkou závodu a chování vašeho kódu je nepředvídatelné.
Funkce společné pro automatické a ruční události
Obvykle jedno nebo více vláken blokuje na EventWaitHandle, dokud vlákno, které není blokováno, nezavolá metodu Set, která uvolní jedno z čekajících vláken (v případě událostí automatického resetování) nebo všechny (v případě událostí ručního resetování). Vlákno může signalizovat EventWaitHandle a pak ho zablokovat jako atomickou operaci voláním statické metody WaitHandle.SignalAndWait.
EventWaitHandle objekty lze použít se statickými WaitHandle.WaitAll a WaitHandle.WaitAny metodami. Můžete použít obě třídy EventWaitHandle a Mutex s těmito metodami, protože obě jsou odvozeny z WaitHandle.
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 platí pro celý systém. 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í je třeba postupovat opatrně. 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. Můžete také použít zabezpečení řízení přístupu pomocí SetAccessControl této metody, ale mezi dobou, kdy se vytvoří zámek čekání na událost, a dobou, kdy je chráněna, ponechává časové okno zranitelnosti. 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:
Na rozdíl od třídy EventWaitHandle mohou odvozené třídy AutoResetEvent a ManualResetEvent představovat pouze místní obslužné rutiny čekání. Nemůžou reprezentovat pojmenované systémové události.