Dela via


EventWaitHandle

Klassen EventWaitHandle tillåter trådar att kommunicera med varandra genom att signalera och genom att vänta på signaler. Händelseväntehandtag (kallas även bara händelser) är väntehandtag som kan signaleras för att släppa en eller flera väntande trådar. När det har signalerats återställs ett händelseväntehandtag manuellt eller automatiskt. Klassen EventWaitHandle kan representera antingen en lokal händelseväntereferens (lokal händelse) eller ett namngivet systemhändelseväntehandtag (namngiven händelse eller systemhändelse, synlig för alla processer).

Kommentar

Händelseväntehandtag är inte .NET-händelser. Det finns inga ombud eller händelsehanterare inblandade. Ordet "händelse" används för att beskriva dem eftersom de traditionellt har kallats operativsystemhändelser, och eftersom handlingen att signalera väntehandtaget anger för väntande trådar att en händelse har inträffat.

Både lokala och namngivna händelseväntereferenser använder systemsynkroniseringsobjekt, som skyddas av SafeWaitHandle omslutningar för att säkerställa att resurserna släpps. Du kan använda Dispose metoden för att frigöra resurserna omedelbart när du är klar med objektet.

Händelseväntehandtag som återställs automatiskt

Du skapar en automatisk återställningshändelse genom att EventResetMode.AutoReset ange när du skapar EventWaitHandle objektet. Som namnet antyder återställs den här synkroniseringshändelsen automatiskt när den signaleras, efter att en enda väntande tråd har släppts. Signalera händelsen genom att anropa dess Set metod.

Automatiska återställningshändelser används vanligtvis för att ge exklusiv åtkomst till en resurs för en enda tråd i taget. En tråd begär resursen genom att anropa WaitOne metoden. Om ingen annan tråd innehåller väntehandtaget returnerar true metoden och den anropande tråden har kontroll över resursen.

Viktigt!

Precis som med alla synkroniseringsmekanismer måste du se till att alla kodsökvägar väntar på rätt väntehandtag innan du får åtkomst till en skyddad resurs. Trådsynkronisering är samarbetsinriktad.

Om en automatisk återställningshändelse signaleras när inga trådar väntar, förblir den signalerad tills en tråd försöker vänta på den. Händelsen släpper tråden och återställs omedelbart och blockerar efterföljande trådar.

Händelseväntehandtag som återställs manuellt

Du skapar en manuell återställningshändelse genom att EventResetMode.ManualReset ange när du skapar EventWaitHandle objektet. Som namnet antyder måste den här synkroniseringshändelsen återställas manuellt efter att den har signalerats. Tills den återställs, genom att anropa dess Reset metod, fortsätter trådar som väntar på händelsehandtaget omedelbart utan att blockera.

En manuell återställningshändelse fungerar som en korrelerings grind. När händelsen inte signaleras blockeras trådar som väntar på den, som hästar i en korrel. När händelsen signaleras kan alla väntande trådar fortsätta genom att anropa dess Set metod. Händelsen förblir signalerad tills dess Reset metod anropas. Detta gör den manuella återställningshändelsen till ett idealiskt sätt att hålla upp trådar som måste vänta tills en tråd har slutfört en uppgift.

Precis som hästar som lämnar en korrelering tar det tid innan de utgivna trådarna schemaläggs av operativsystemet och återupptar körningen. Reset Om metoden anropas innan alla trådar har återupptagit körningen blockeras de återstående trådarna igen. Vilka trådar som återupptas och vilka trådar som blockeras beror på slumpmässiga faktorer som belastningen på systemet, antalet trådar som väntar på schemaläggaren och så vidare. Detta är inte ett problem om tråden som signalerar händelsen slutar efter signalering, vilket är det vanligaste användningsmönstret. Om du vill att tråden som signalerade händelsen ska starta en ny aktivitet när alla väntande trådar har återupptagits, måste du blockera den tills alla väntande trådar har återupptagits. Annars har du ett konkurrenstillstånd och kodens beteende är oförutsägbart.

Funktioner som är gemensamma för automatiska och manuella händelser

Vanligtvis blockeras en eller flera trådar på en EventWaitHandle tills en avblockerad tråd anropar Set metoden, som släpper ut en av de väntande trådarna (vid automatiska återställningshändelser) eller alla (vid manuella återställningshändelser). En tråd kan signalera en EventWaitHandle och sedan blockera den, som en atomisk åtgärd, genom att anropa den statiska WaitHandle.SignalAndWait metoden.

EventWaitHandle objekt kan användas med statiska WaitHandle.WaitAll objekt och WaitHandle.WaitAny metoder. Eftersom klasserna EventWaitHandle och Mutex båda härleds från WaitHandlekan du använda båda klasserna med dessa metoder.

Namngivna händelser

Windows-operativsystemet tillåter att händelseväntehandtag har namn. En namngiven händelse är systemomfattande. När den namngivna händelsen har skapats visas den för alla trådar i alla processer. Namngivna händelser kan därför användas för att synkronisera både processers och trådars aktiviteter.

Du kan skapa ett EventWaitHandle objekt som representerar en namngiven systemhändelse med hjälp av någon av konstruktorerna som anger ett händelsenamn.

Kommentar

Eftersom namngivna händelser är systemomfattande är det möjligt att ha flera EventWaitHandle objekt som representerar samma namngivna händelse. Varje gång du anropar en konstruktor eller OpenExisting metoden skapas ett nytt EventWaitHandle objekt. Om du anger samma namn upprepade gånger skapas flera objekt som representerar samma namngivna händelse.

Försiktighet rekommenderas vid användning av namngivna händelser. Eftersom de är systemomfattande kan en annan process som använder samma namn blockera dina trådar oväntat. Skadlig kod som körs på samma dator kan använda detta som grund för en överbelastningsattack.

Använd åtkomstkontrollsäkerhet för att skydda ett EventWaitHandle objekt som representerar en namngiven händelse, helst med hjälp av en konstruktor som anger ett EventWaitHandleSecurity objekt. Du kan också använda åtkomstkontrollsäkerhet med hjälp SetAccessControl av metoden, men detta lämnar ett fönster av sårbarhet mellan tiden då händelseväntehandtaget skapas och den tid det skyddas. Att skydda händelser med åtkomstkontrollsäkerhet hjälper till att förhindra skadliga attacker, men det löser inte problemet med oavsiktliga namnkollisioner.

Kommentar

EventWaitHandle Till skillnad från klassen kan de härledda klasserna AutoResetEvent och ManualResetEvent endast representera lokala väntereferenser. De kan inte representera namngivna systemhändelser.

Se även