Hantera och utlösa händelser
Händelser i .NET baseras på delegeringsmodellen. Ombudsmodellen följer designmönstret observer, som gör det möjligt för en prenumerant att registrera sig med och ta emot meddelanden från en leverantör. En händelseavsändare skickar ett meddelande när en händelse inträffar. En händelsemottagare definierar svaret. Den här artikeln beskriver huvudkomponenterna i ombudsmodellen, hur du använder händelser i program och hur du implementerar händelser i koden.
Utlösa händelser med en händelsesändare
En händelse är ett meddelande som skickas av ett objekt för att signalera förekomsten av en åtgärd. Åtgärden kan vara användarinteraktion, till exempel en knapptryckning, eller så kan det bero på annan programlogik, till exempel en ändring av egenskapsvärdet. Objektet som genererar händelsen kallas händelsesändare. Händelsesändaren känner inte till det objekt eller den metod som tar emot (hanterar) de händelser som genereras. Händelsen är vanligtvis medlem i händelsesändaren. Händelsen Click är till exempel medlem i klassen Button och händelsen PropertyChanged är medlem i den klass som implementerar INotifyPropertyChanged-gränssnittet.
För att definiera en händelse använder du C# händelse eller nyckelordet Visual Basic Event i signaturen för händelseklassen och anger typen av ombud för händelsen. Ombud beskrivs i nästa avsnitt.
För att skapa en händelse lägger du vanligtvis till en metod som är markerad som protected
och virtual
(i C#) eller Protected
och Overridable
(i Visual Basic). Namngivningskonventionen för metoden är On<EventName>
, till exempel OnDataReceived
. Metoden ska ta en parameter som anger ett händelsedataobjekt, som är ett objekt av typen EventArgs eller en härledd typ. Du anger den här metoden för att möjliggöra för härledda klasser att åsidosätta logiken för att utlösa händelsen. En härledd klass bör alltid anropa grundklassens metod On<EventName>
för att säkerställa att de registrerade delegaterna tar emot händelsen.
I följande exempel visas hur du deklarerar en händelse med namnet ThresholdReached
. Händelsen är associerad med EventHandler ombudet och genereras i en metod med namnet OnThresholdReached
:
class Counter
{
public event EventHandler ThresholdReached;
protected virtual void OnThresholdReached(EventArgs e)
{
ThresholdReached?.Invoke(this, e);
}
// provide remaining implementation for the class
}
Public Class Counter
Public Event ThresholdReached As EventHandler
Protected Overridable Sub OnThresholdReached(e As EventArgs)
RaiseEvent ThresholdReached(Me, e)
End Sub
' provide remaining implementation for the class
End Class
Deklarera ombudssignaturer för händelsehanterare
En delegat är en typ som innehåller en referens till en metod. Ett ombud deklareras med en signatur som visar returtypen och parametrarna för de metoder som den refererar till. Den kan endast innehålla referenser till metoder som matchar dess signatur. En delegat motsvarar en typsäker funktionspekare eller en callback-funktion. En ombudsdeklaration räcker för att definiera en ombudsklass.
Ombud har många användningsområden i .NET. I händelsesammanhang är ett ombud en mellanhand (eller pekarliknande mekanism) mellan händelsekällan och koden som hanterar händelsen. Du associerar ett ombud med en händelse genom att inkludera ombudstypen i händelsedeklarationen, som du ser i exemplet i föregående avsnitt. Mer information om ombud finns i klassen Delegate.
.NET tillhandahåller delegaterna EventHandler och EventHandler<TEventArgs> för att stödja de flesta händelsescenarier. Använd EventHandler-delegeringen för alla händelser som inte innehåller händelsedata. Använd delegeringen EventHandler<TEventArgs> för händelser som innehåller data om händelsen. Dessa delegater har inget returvärde och tar två parametrar (ett objekt för källan till händelsen och ett objekt för händelsedata).
Delegater är multicast klassobjekt, vilket innebär att de kan innehålla referenser till mer än en metod för händelsehantering. Mer information finns på referenssidan för Delegate. Ombud ger flexibilitet och detaljerad kontroll vid händelsehantering. Ett ombud fungerar som händelseutskickare för klassen som genererar händelsen genom att underhålla en lista över registrerade händelsehanterare för händelsen.
Använd de EventHandler- och EventHandler<TEventArgs> ombudstyperna för att definiera det ombud som behövs. Du markerar en delegering med delegate
typ i [C#](../../csharp/language-reference/builtin-types/reference-types.md#the-delegate-type) eller Delegate
typ i Visual Basic i deklarationen. I följande exempel visas hur du deklarerar ett ombud med namnet ThresholdReachedEventHandler
:
public delegate void ThresholdReachedEventHandler(object sender, ThresholdReachedEventArgs e);
Public Delegate Sub ThresholdReachedEventHandler(sender As Object, e As ThresholdReachedEventArgs)
Arbeta med händelsedataklasser
Data som är associerade med en händelse kan tillhandahållas via en händelsedataklass. .NET tillhandahåller många händelsedataklasser som du kan använda i dina program. Klassen SerialDataReceivedEventArgs är till exempel händelsedataklassen för händelsen SerialPort.DataReceived. .NET följer ett namngivningsmönster där alla händelsedataklasser slutar med suffixet EventArgs
. Du avgör vilken händelsedataklass som är associerad med en händelse genom att titta på ombudet för händelsen. Till exempel inkluderar delegeringen SerialDataReceivedEventHandler klassen SerialDataReceivedEventArgs som en parameter.
Klassen EventArgs är vanligtvis bastypen för händelsedataklasser. Du använder också den här klassen om en händelse inte har några data associerade med den. När du skapar en händelse som meddelar prenumeranter att något har hänt utan ytterligare data, bör du inkludera klassen EventArgs som den andra parametern i delegeringen. Du kan skicka EventArgs.Empty-värdet när inga data anges. EventHandler-ombudet inkluderar klassen EventArgs som parameter.
Du kan skapa en klass som härleds från klassen EventArgs för att tillhandahålla alla medlemmar som behövs för att skicka data som är relaterade till händelsen. Vanligtvis bör du använda samma namngivningsmönster som .NET och avsluta händelsedataklassnamnet med EventArgs
suffixet.
I följande exempel visas en händelsedataklass med namnet ThresholdReachedEventArgs
som innehåller egenskaper som är specifika för händelsen som genereras:
public class ThresholdReachedEventArgs : EventArgs
{
public int Threshold { get; set; }
public DateTime TimeReached { get; set; }
}
Public Class ThresholdReachedEventArgs
Inherits EventArgs
Public Property Threshold As Integer
Public Property TimeReached As DateTime
End Class
Svara på händelser med hanterare
För att svara på en händelse definierar du en händelsehanterarmetod i händelsemottagaren. Den här metoden måste matcha signaturen för ombudet för händelsen du hanterar. I händelsehanteraren utför du de åtgärder som krävs när händelsen aktiveras, till exempel att samla in användarindata när användaren trycker på en knapp. Om du vill ta emot meddelanden när händelsen inträffar måste händelsehanterarmetoden prenumerera på händelsen.
I följande exempel visas en händelsehanterarmetod med namnet c_ThresholdReached
som matchar signaturen för EventHandler-ombudet. Metoden prenumererar på händelsen ThresholdReached
:
class ProgramTwo
{
static void Main()
{
var c = new Counter();
c.ThresholdReached += c_ThresholdReached;
// provide remaining implementation for the class
}
static void c_ThresholdReached(object sender, EventArgs e)
{
Console.WriteLine("The threshold was reached.");
}
}
Module Module1
Sub Main()
Dim c As New Counter()
AddHandler c.ThresholdReached, AddressOf c_ThresholdReached
' provide remaining implementation for the class
End Sub
Sub c_ThresholdReached(sender As Object, e As EventArgs)
Console.WriteLine("The threshold was reached.")
End Sub
End Module
Använda statiska och dynamiska händelsehanterare
Med .NET kan prenumeranter registrera sig för händelsemeddelanden statiskt eller dynamiskt. Statiska händelsehanterare gäller under hela klassens livslängd vars händelser de hanterar. Dynamiska händelsehanterare aktiveras och inaktiveras uttryckligen under programkörningen, vanligtvis som svar på viss logik för villkorsstyrda program. Du kan använda dynamiska hanterare när händelsemeddelanden endast behövs under vissa förhållanden, eller när körningsvillkor avgör vilken hanterare som ska anropas. Exemplet i föregående avsnitt visar hur du dynamiskt lägger till en händelsehanterare. Mer information finns i Events (i Visual Basic) och Events (i C#).
Utlös flera händelser
Om klassen genererar flera händelser genererar kompilatorn ett fält per händelsedelegatinstans. Om antalet händelser är stort kanske lagringskostnaden för ett fält per ombud inte är acceptabel. I dessa scenarier tillhandahåller .NET händelseegenskaper som du kan använda med en annan datastruktur som du väljer för att lagra händelsedelegater.
Händelseegenskaper består av händelsedeklarationer tillsammans med händelseåtkomster. Händelseåtkomster är metoder som du definierar för att lägga till eller ta bort händelsedelegatinstanser från lagringsdatastrukturen.
Anmärkning
Händelseegenskaperna är långsammare än händelsefälten eftersom varje händelsedelegat måste hämtas innan den kan anropas.
Kompromissen är mellan minne och hastighet. Om klassen definierar många händelser som sällan genereras bör du implementera händelseegenskaper. Mer information finns i Hantera flera händelser med hjälp av händelseegenskaper.
Utforska relaterade uppgifter
Följande resurser beskriver andra uppgifter och begrepp som rör arbete med händelser:
- Höja och konsumera händelser: Hitta exempel på att höja och konsumera händelser.
- Hantera flera händelser med händelseegenskaper: Identifiera hur du använder händelseegenskaper för att hantera flera händelser.
- Utforska övervakningsdesignmönstret: Granska ett designmönster som gör att en prenumerant kan registrera sig med och ta emot meddelanden från en leverantör.
Granska referens för specifikation
Dokumentation för specifikationsreferenser är tillgänglig för de API:er som stöder händelsehantering.
API-namn | API-typ | Hänvisning |
---|---|---|
EventHandler | Delegera | EventHandler |
EventHandler<TEventArgs> | Delegera | EventHandler<TEventArgs> |
EventArgs | Klass | EventArgs |
Delegera | Klass | Delegate |