Zpracování a vyvolávání událostí

Události v .NET jsou založené na modelu delegáta. Model delegáta se řídí vzorem návrhu pozorovatele, který umožňuje předplatiteli zaregistrovat se a přijímat oznámení od poskytovatele. Odesílatel události odešle oznámení, že se událost stala, a příjemce události obdrží toto oznámení a definuje odpověď na ni. Tento článek popisuje hlavní součásti modelu delegáta, jak využívat události v aplikacích a jak implementovat události v kódu.

událost

Událost je zpráva odeslaná objektem, která signalizovala výskyt akce. Akce může být způsobená interakcí uživatele, například kliknutím na tlačítko, nebo může mít za následek jinou logiku programu, například změnu hodnoty vlastnosti. Objekt, který vyvolá událost, se nazývá odesílatel události. Odesílatel události neví, který objekt nebo metoda obdrží (zpracuje) události, které vyvolá. Událost je obvykle členem odesílatele události; Click Například událost je členem Button třídy a PropertyChanged událost je členem třídy, která implementuje INotifyPropertyChanged rozhraní.

K definování události použijete klíčové slovo C# event nebo Visual Basic Event v podpisu třídy událostí a zadáte typ delegáta události. Delegáti jsou popsáni v další části.

K vyvolání události obvykle přidáte metodu označenou jako protected a virtual (v jazyce C#) nebo ProtectedOverridable (v Visual Basic). Pojmenujte tuto metodu OnEventName, například OnDataReceived. Metoda by měla mít jeden parametr, který určuje datový objekt události, což je objekt typu EventArgs nebo odvozený typ. Tuto metodu zadáte tak, aby odvozené třídy přepsaly logiku pro vyvolání události. Odvozená třída by měla vždy volat metodu OnEventName základní třídy, aby se zajistilo, že zaregistrovaní delegáti obdrží událost.

Následující příklad ukazuje, jak deklarovat událost pojmenovanou ThresholdReached. Událost je přidružena delegátovi EventHandler a vyvolána v metodě s názvem OnThresholdReached.

class Counter
{
    public event EventHandler ThresholdReached;

    protected virtual void OnThresholdReached(EventArgs e)
    {
        EventHandler handler = ThresholdReached;
        handler?.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

Delegáti

Delegát je typ, který obsahuje odkaz na metodu. Delegát je deklarován podpisem, který zobrazuje návratový typ a parametry pro metody, na které odkazuje, a může obsahovat odkazy pouze na metody, které odpovídají jeho podpisu. Delegát je tedy ekvivalentní ukazateli funkce bezpečného typu nebo zpětnému volání. Deklarace delegáta je dostatečná k definování třídy delegáta.

Delegáti mají mnoho použití v .NET. V kontextu událostí je delegát mezi zdrojem událostí a kódem, který zpracovává událost, zprostředkující (nebo mechanismus podobný ukazateli). Delegáta přidružíte k události zahrnutím typu delegáta do deklarace události, jak je znázorněno v příkladu v předchozí části. Další informace odelegátch Delegate

.NET poskytuje EventHandler a EventHandler<TEventArgs> delegáty pro podporu většiny scénářů událostí. Použijte delegáta EventHandler pro všechny události, které neobsahují data událostí. Použijte delegáta EventHandler<TEventArgs> pro události, které obsahují data o události. Tito delegáti nemají žádnou návratovou hodnotu typu a přebírají dva parametry (objekt pro zdroj události a objekt pro data události).

Delegáti jsou vícesměrové vysílání, což znamená, že můžou obsahovat odkazy na více než jednu metodu zpracování událostí. Podrobnosti najdete na Delegate referenční stránce. Delegáti poskytují flexibilitu a jemně odstupňované řízení při zpracování událostí. Delegát funguje jako dispečer událostí pro třídu, která vyvolá událost tím, že udržuje seznam registrovaných obslužných rutin událostí pro událost.

V situacích, kdy EventHandler delegáti EventHandler<TEventArgs> nefungují, můžete definovat delegáta. Scénáře, které vyžadují, abyste definovali delegáta, jsou velmi vzácné, například když musíte pracovat s kódem, který nerozpozná obecné typy. Delegáta označíte pomocí jazyka C# delegate a Visual Basic Delegate klíčové slovo v deklaraci. Následující příklad ukazuje, jak deklarovat delegáta s názvem ThresholdReachedEventHandler.

public delegate void ThresholdReachedEventHandler(object sender, ThresholdReachedEventArgs e);
Public Delegate Sub ThresholdReachedEventHandler(sender As Object, e As ThresholdReachedEventArgs)

Data událostí

Data přidružená k události je možné poskytnout prostřednictvím datové třídy události. .NET poskytuje mnoho datových tříd událostí, které můžete použít ve svých aplikacích. Třída je například SerialDataReceivedEventArgs datová třída události pro SerialPort.DataReceived událost. .NET se řídí vzorem pojmenování ukončení všech datových tříd událostí .EventArgs Určíte, která datová třída událostí je přidružená k události, a to tak, že se podíváte na delegáta události. Delegát například SerialDataReceivedEventHandler obsahuje SerialDataReceivedEventArgs třídu jako jeden z jeho parametrů.

Třída EventArgs je základním typem pro všechny třídy dat událostí. EventArgs je také třída, kterou používáte, pokud událost nemá přidružená žádná data. Když vytvoříte událost, která je určená pouze k upozornění jiných tříd, že se něco stalo a nemusí předávat žádná data, zahrňte EventArgs třídu jako druhý parametr delegáta. Hodnotu můžete předat EventArgs.Empty , pokud nejsou k dispozici žádná data. Delegát EventHandler zahrnuje EventArgs třídu jako parametr.

Pokud chcete vytvořit přizpůsobenou datovou třídu událostí, vytvořte třídu, která je odvozena od EventArgs, a pak zadejte všechny členy potřebné k předávání dat, která souvisejí s událostí. Obvykle byste měli použít stejný vzor pojmenování jako .NET a ukončit název třídy dat události .EventArgs

Následující příklad ukazuje datovou třídu události s názvem ThresholdReachedEventArgs. Obsahuje vlastnosti specifické pro vyvolání události.

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

Obslužné rutiny událostí

Chcete-li reagovat na událost, definujete metodu obslužné rutiny události v přijímači událostí. Tato metoda musí odpovídat podpisu delegáta pro událost, kterou zpracováváte. V obslužné rutině události provedete akce potřebné při vyvolání události, například shromažďování uživatelského vstupu po kliknutí na tlačítko. Pokud chcete dostávat oznámení, když dojde k události, musí se vaše metoda obslužné rutiny události přihlásit k odběru události.

Následující příklad ukazuje metodu obslužné rutiny události s názvem c_ThresholdReached , která odpovídá podpisu delegáta EventHandler . Metoda se přihlásí k odběru ThresholdReached události.

class Program
{
    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

Statické a dynamické obslužné rutiny událostí

.NET umožňuje předplatitelům registrovat oznámení událostí staticky nebo dynamicky. Statické obslužné rutiny událostí se projeví po celou dobu životnosti třídy, jejíž události zpracovávají. Dynamické obslužné rutiny událostí se explicitně aktivují a deaktivují během provádění programu, obvykle v reakci na nějakou logiku podmíněného programu. Dají se například použít, pokud jsou oznámení událostí potřebná pouze za určitých podmínek nebo pokud aplikace poskytuje více obslužných rutin událostí a podmínky běhu definují odpovídající, které se mají použít. Příklad v předchozí části ukazuje, jak dynamicky přidat obslužnou rutinu události. Další informace najdete v tématu Události (v Visual Basic) a Události (v jazyce C#).

Vyvolání více událostí

Pokud vaše třída vyvolá více událostí, kompilátor vygeneruje jedno pole pro instanci delegáta události. Pokud je počet událostí velký, náklady na úložiště jednoho pole na delegáta nemusí být přijatelné. V takových situacích poskytuje .NET vlastnosti událostí, které můžete použít s jinou datovou strukturou podle vašeho výběru k ukládání delegátů událostí.

Vlastnosti události se skládají z deklarací událostí doprovázených příslušenstvím událostí. Přístupové objekty událostí jsou metody, které definujete pro přidání nebo odebrání instancí delegátů událostí ze struktury dat úložiště. Všimněte si, že vlastnosti událostí jsou pomalejší než pole událostí, protože každý delegát události musí být načten před vyvolání. Kompromis je mezi pamětí a rychlostí. Pokud vaše třída definuje mnoho událostí, které jsou zřídka vyvolány, budete chtít implementovat vlastnosti události. Další informace naleznete v tématu Postupy: Zpracování více událostí pomocí vlastností události.

Nadpis Popis
Postupy: Vyvolávání a zpracovávání událostí Obsahuje příklady vyvolání a využívání událostí.
Postupy: Zpracování více událostí pomocí vlastností událostí Ukazuje, jak pomocí vlastností událostí zpracovat více událostí.
Vzor návrhu pozorovatele Popisuje vzor návrhu, který předplatiteli umožňuje registraci a přijímání oznámení od poskytovatele.

Viz také