Obsługa i zgłaszanie zdarzeń

Zdarzenia na .NET są oparte na modelu delegowanym. Model delegata jest zgodny ze wzorcem projektowym obserwatora, który umożliwia subskrybentowi zarejestrowanie się i odbieranie powiadomień od dostawcy. Nadawca zdarzenia wypycha powiadomienie o zdarzeniu, a odbiornik odbiera to powiadomienie i definiuje na nie odpowiedź. W tym artykule opisano główne składniki modelu delegata, sposób zużywania zdarzeń w aplikacjach oraz sposób implementowanie zdarzeń w kodzie.

Zdarzenia

Zdarzenie to komunikat wysyłany przez obiekt w celu sygnalizowania wystąpienia akcji. Akcja może być spowodowana przez interakcję użytkownika, na przykład kliknięcie przycisku, lub może być spowodowana przez inną logikę programu, taką jak zmiana wartości właściwości. Obiekt, który wywołuje zdarzenie, jest nazywany nadawcą zdarzenia. Nadawca zdarzenia nie wie, który obiekt lub metoda otrzyma (obsłuży) zdarzenia, które zgłasza. Zdarzenie jest zazwyczaj członkiem nadawcy zdarzenia. Na przykład zdarzenie jest członkiem klasy, a zdarzenie jest członkiem klasy, Click Button która PropertyChanged implementuje INotifyPropertyChanged interfejs.

Aby zdefiniować zdarzenie, należy użyć słowa kluczowego C# lub Visual Basic w sygnaturze klasy zdarzeń i określić typ delegata event Event dla zdarzenia. Delegaci są opisani w następnej sekcji.

Zwykle, aby podnieść zdarzenie, należy dodać metodę, która jest oznaczona jako protected i virtual (w języku C#) lub Protected i Overridable (w Visual Basic). Nadaj tej metodzie On nazwę EventName, na przykład OnDataReceived . Metoda powinna przyjmować jeden parametr określający obiekt danych zdarzenia, który jest obiektem typu EventArgs lub typem pochodnym. Należy podać tę metodę, aby umożliwić klasom pochodnym przesłonięcie logiki do wystąpienia zdarzenia. Klasa pochodna powinna zawsze wywołać metodę EventName klasy bazowej, aby upewnić się, że zarejestrowani On delegaci odbierają zdarzenie.

Poniższy przykład pokazuje, jak zadeklarować zdarzenie o nazwie ThresholdReached . Zdarzenie jest skojarzone z delegatem EventHandler i wywoływane w metodzie o nazwie 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

Delegaci

Delegat jest typem, który przechowuje odwołanie do metody. Delegat jest zadeklarowany z podpisem, który pokazuje zwracany typ i parametry dla metod, do których się odwołuje, i może przechowywać odwołania tylko do metod, które pasują do jego podpisu. Delegat jest zatem odpowiednikiem wskaźnika funkcji bezpiecznej pod typem lub wywołania zwrotnego. Deklaracja delegata jest wystarczająca do zdefiniowania klasy delegata.

Delegaci mają wiele zastosowań na .NET. W kontekście zdarzeń delegat jest elementem pośredniczącym (lub mechanizmem przypominacym wskaźnik) między źródłem zdarzenia a kodem, który obsługuje zdarzenie. Delegata można skojarzyć ze zdarzeniem, uwzględniając typ delegata w deklaracji zdarzenia, jak pokazano w przykładzie w poprzedniej sekcji. Aby uzyskać więcej informacji na temat delegatów, zobacz Delegate klasę .

.NET udostępnia EventHandler delegatów i EventHandler<TEventArgs> do obsługi większości scenariuszy zdarzeń. Użyj EventHandler delegata dla wszystkich zdarzeń, które nie zawierają danych zdarzenia. Użyj EventHandler<TEventArgs> delegata dla zdarzeń, które zawierają dane dotyczące zdarzenia. Te delegaty nie mają zwracanej wartości typu i mają dwa parametry (obiekt dla źródła zdarzenia i obiekt dla danych zdarzenia).

Delegaci są multiemisją,co oznacza, że mogą przechowywać odwołania do więcej niż jednej metody obsługi zdarzeń. Aby uzyskać szczegółowe informacje, zobacz Delegate stronę referencyjną. Delegaci zapewniają elastyczność i maksymalną kontrolę w obsłudze zdarzeń. Delegat działa jako dyspozytor zdarzeń dla klasy, która wywołuje zdarzenie, utrzymując listę zarejestrowanych programów obsługi zdarzeń dla zdarzenia.

W EventHandler scenariuszach, w EventHandler<TEventArgs> których delegaci i nie działają, można zdefiniować delegata. Scenariusze wymagające zdefiniowania delegata są bardzo rzadkie, na przykład gdy trzeba pracować z kodem, który nie rozpoznaje typów ogólnych. Delegata należy oznaczyć za pomocą języka C# delegate Visual Basic Delegate słowa kluczowego w deklaracji . W poniższym przykładzie pokazano, jak zadeklarować delegata o nazwie ThresholdReachedEventHandler .

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

Dane zdarzenia

Dane skojarzone ze zdarzeniem można dostarczać za pośrednictwem klasy danych zdarzenia. .NET udostępnia wiele klas danych zdarzeń, których można używać w aplikacjach. Na przykład klasa SerialDataReceivedEventArgs jest klasą danych zdarzeń SerialPort.DataReceived dla zdarzenia. .NET jest zgodny ze wzorcem nazewnictwa, który kończy wszystkie klasy danych zdarzeń na EventArgs . Aby określić, która klasa danych zdarzeń jest skojarzona ze zdarzeniem, należy sprawdzić delegata dla zdarzenia. Na przykład delegat SerialDataReceivedEventHandler zawiera SerialDataReceivedEventArgs klasę jako jeden z jego parametrów.

Klasa EventArgs jest typem bazowym dla wszystkich klas danych zdarzeń. EventArgs jest również klasą używaną, gdy zdarzenie nie ma skojarzonych żadnych danych. Podczas tworzenia zdarzenia, które ma na celu tylko powiadamianie innych klas, że coś się stało i nie trzeba przekazywać żadnych danych, dołącz klasę jako drugi parametr EventArgs w delegacie. Możesz przekazać EventArgs.Empty wartość, jeśli nie podano żadnych danych. Delegat EventHandler zawiera EventArgs klasę jako parametr.

Jeśli chcesz utworzyć niestandardową klasę danych zdarzeń, utwórz klasę pochodzącą od klasy , a następnie podaj wszystkie składowe potrzebne do przekazania danych powiązanych EventArgs ze zdarzeniem. Zazwyczaj należy użyć tego samego wzorca nazewnictwa co program .NET i zakończyć nazwę klasy danych zdarzeń za pomocą . EventArgs

W poniższym przykładzie pokazano klasę danych zdarzeń o nazwie ThresholdReachedEventArgs . Zawiera właściwości specyficzne dla wywoływanego zdarzenia.

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

Procedury obsługi zdarzeń

Aby odpowiedzieć na zdarzenie, należy zdefiniować metodę obsługi zdarzeń w odbiorcy zdarzeń. Ta metoda musi odpowiadać podpisowi delegata dla zdarzenia, które jest przez Ciebie obsługi. W programie obsługi zdarzeń wykonujesz akcje, które są wymagane po zdarzeniu, takie jak zbieranie danych wejściowych użytkownika po kliknięciu przycisku przez użytkownika. Aby otrzymywać powiadomienia w przypadku wystąpienia zdarzenia, metoda obsługi zdarzeń musi subskrybować zdarzenie.

W poniższym przykładzie pokazano metodę obsługi zdarzeń o nazwie c_ThresholdReached , która odpowiada podpisowi EventHandler delegata. Metoda subskrybuje ThresholdReached zdarzenie.

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

Statyczne i dynamiczne programy obsługi zdarzeń

.NET umożliwia subskrybentom rejestrowanie powiadomień o zdarzeniach statycznie lub dynamicznie. Statyczne procedury obsługi zdarzeń są dostępne przez cały czas życia klasy, której obsługują zdarzenia. Dynamiczne programy obsługi zdarzeń są jawnie aktywowane i dezaktywowane podczas wykonywania programu, zazwyczaj w odpowiedzi na logikę programu warunkowego. Na przykład mogą być używane, jeśli powiadomienia o zdarzeniach są potrzebne tylko w określonych warunkach lub jeśli aplikacja udostępnia wiele programów obsługi zdarzeń, a warunki czasu uruchamiania definiują odpowiednią do użycia. W przykładzie w poprzedniej sekcji pokazano, jak dynamicznie dodać program obsługi zdarzeń. Aby uzyskać więcej informacji, zobacz Zdarzenia (w języku Visual Basic) i Zdarzenia (w języku C#).

Podnoszenie wielu zdarzeń

Jeśli klasa zgłasza wiele zdarzeń, kompilator generuje jedno pole na wystąpienie delegata zdarzenia. Jeśli liczba zdarzeń jest duża, koszt magazynu jednego pola na delegata może być niedopuszczalny. W takich sytuacjach .NET udostępnia właściwości zdarzenia, których można używać z inną strukturą danych do przechowywania delegatów zdarzeń.

Właściwości zdarzenia składają się z deklaracji zdarzeń, którym towarzyszą konstruktory dostępu zdarzeń. Metody dostępu zdarzeń to metody, które definiuje się w celu dodawania lub usuwania wystąpień delegatów zdarzeń ze struktury danych magazynu. Należy pamiętać, że właściwości zdarzenia są wolniejsze niż pola zdarzeń, ponieważ każdy obiekt delegowany zdarzenia musi zostać pobrany przed jego wywołaniem. Różnica między pamięcią i szybkością. Jeśli klasa definiuje wiele rzadko wywoływanych zdarzeń, należy zaimplementować właściwości zdarzenia. Aby uzyskać więcej informacji, zobacz How to: Handle Multiple Events Using Event Properties(Jak obsługiwać wiele zdarzeń przy użyciu właściwości zdarzenia).

Tytuł Opis
Porady: wywoływanie zdarzeń i korzystanie z nich Zawiera przykłady podnoszenia i zużywania zdarzeń.
Instrukcje: Obsługa wielu zdarzeń przy użyciu właściwości zdarzenia Pokazuje, jak używać właściwości zdarzenia do obsługi wielu zdarzeń.
Wzorzec projektowy obserwatora Opisuje wzorzec projektowy, który umożliwia subskrybentowi zarejestrowanie się u dostawcy i odbieranie powiadomień od dostawcy.

Zobacz też