F # - Ereignisse

Mit Ereignissen können Klassen Nachrichten untereinander senden und empfangen.

In der GUI sind Ereignisse Benutzeraktionen wie Tastendruck, Klicks, Mausbewegungen usw. oder ein Ereignis wie vom System generierte Benachrichtigungen. Anwendungen müssen auf Ereignisse reagieren, wenn sie auftreten. Zum Beispiel Interrupts. Ereignisse werden für die Kommunikation zwischen Prozessen verwendet.

Objekte kommunizieren durch synchrones Weiterleiten von Nachrichten miteinander.

Ereignisse sind mit anderen Funktionen verbunden. Objekte registrierencallback Funktionen für ein Ereignis, und diese Rückrufe werden ausgeführt, wenn (und wenn) das Ereignis von einem Objekt ausgelöst wird.

Die Ereignisklasse und das Ereignismodul

Die Control.Event <'T> -Klasse hilft beim Erstellen eines beobachtbaren Objekts oder Ereignisses.

Es hat die folgenden Instanzmitglieder, um mit den Ereignissen zu arbeiten -

Mitglied Beschreibung
Veröffentlichen Veröffentlicht eine Beobachtung als erstklassigen Wert.
Auslösen Löst eine Beobachtung mit den angegebenen Parametern aus.

Das Control.Event-Modul bietet Funktionen zum Verwalten von Ereignisströmen -

Wert Beschreibung
hinzufügen: ('T → Einheit) → Ereignis <' Entf, 'T> → Einheit Führt die angegebene Funktion jedes Mal aus, wenn das angegebene Ereignis ausgelöst wird.
Wählen Sie: (Option 'T →' U) → IEvent <'Del,' T> → IEvent <'U> Gibt ein neues Ereignis zurück, das bei einer Auswahl von Nachrichten aus dem ursprünglichen Ereignis ausgelöst wird. Die Auswahlfunktion wandelt eine ursprüngliche Nachricht in eine optionale neue Nachricht um.
Filter: ('T → bool) → IEvent <' Del, 'T> → IEvent <' T> Gibt ein neues Ereignis zurück, das das ursprüngliche Ereignis abhört und das resultierende Ereignis nur auslöst, wenn das Argument für das Ereignis die angegebene Funktion übergibt.
Karte: ('T →' U) → IEvent <'Del,' T> → IEvent <'U> Gibt ein neues Ereignis zurück, das von der angegebenen Funktion transformierte Werte übergibt.
Zusammenführen: IEvent <'Del1,' T> → IEvent <'Del2,' T> → IEvent <'T> Löst das Ausgabeereignis aus, wenn eines der Eingabeereignisse ausgelöst wird.
paarweise: IEvent <'Del,' T> → IEvent <'T *' T> Gibt ein neues Ereignis zurück, das beim zweiten und nachfolgenden Auslösen des Eingabeereignisses ausgelöst wird. DasNth Das Auslösen des Eingabeereignisses übergibt die Argumente aus dem N-1th und Nthals Paar auslösen. Das Argument ging an dieN-1th Die Auslösung wird bis zum Nth Auslösung erfolgt.
Partition: ('T → bool) → IEvent <' Del, 'T> → IEvent <' T> * IEvent <'T> Gibt ein neues Ereignis zurück, das das ursprüngliche Ereignis abhört und das erste resultierende Ereignis auslöst, wenn die Anwendung des Prädikats auf die Ereignisargumente true zurückgibt, und das zweite Ereignis, wenn es false zurückgibt.
Scan: ('U →' T → 'U) →' U → IEvent <'Del,' T> → IEvent <'U> Gibt ein neues Ereignis zurück, das aus den Ergebnissen der Anwendung der angegebenen Akkumulationsfunktion auf aufeinanderfolgende Werte besteht, die für das Eingabeereignis ausgelöst wurden. Ein Element des internen Status zeichnet den aktuellen Wert des Statusparameters auf. Der interne Status ist während der Ausführung der Akkumulationsfunktion nicht gesperrt. Daher sollte darauf geachtet werden, dass das Eingabe-IEvent nicht von mehreren Threads gleichzeitig ausgelöst wird.
Aufteilung: ('T → Auswahl <' U1, 'U2>) → IEvent <' Entf, 'T> → IEvent <' U1> * IEvent <'U2> Gibt ein neues Ereignis zurück, das das ursprüngliche Ereignis abhört und das erste resultierende Ereignis auslöst, wenn die Anwendung der Funktion auf die Ereignisargumente ein Choice1Of2 zurückgibt, und das zweite Ereignis, wenn es ein Choice2Of2 zurückgibt.

Ereignisse erstellen

Ereignisse werden über das erstellt und verwendet EventKlasse. Der Ereigniskonstruktor wird zum Erstellen eines Ereignisses verwendet.

Beispiel

type Worker(name : string, shift : string) =
   let mutable _name = name;
   let mutable _shift = shift;
   let nameChanged = new Event<unit>() (* creates event *)
   let shiftChanged = new Event<unit>() (* creates event *)

   member this.Name
      with get() = _name
      and set(value) = _name <- value

   member this.Shift
      with get() = _shift
      and set(value) = _shift <- value

Danach müssen Sie das Feld nameChanged als öffentliches Mitglied verfügbar machen, damit die Listener sich an das Ereignis anschließen können, für das Sie das verwenden Publish Eigentum der Veranstaltung -

type Worker(name : string, shift : string) =
   let mutable _name = name;
   let mutable _shift = shift;

   let nameChanged = new Event<unit>() (* creates event *)
   let shiftChanged = new Event<unit>() (* creates event *)

   member this.NameChanged = nameChanged.Publish (* exposed event handler *)
   member this.ShiftChanged = shiftChanged.Publish (* exposed event handler *)

   member this.Name
      with get() = _name
      and set(value) = _name <- value
      nameChanged.Trigger() (* invokes event handler *)

   member this.Shift
      with get() = _shift
      and set(value) = _shift <- value
   shiftChanged.Trigger() (* invokes event handler *)

Als Nächstes fügen Sie Ereignishandlern Rückrufe hinzu. Jeder Ereignishandler hat den Typ IEvent <'T>, der verschiedene Methoden bereitstellt -

Methode Beschreibung
val Add: event :( 'T → unit) → unit Verbindet eine Listener-Funktion mit dem Ereignis. Der Listener wird aufgerufen, wenn das Ereignis ausgelöst wird.
val AddHandler: 'del → unit Verbindet ein Handler-Delegatenobjekt mit dem Ereignis. Ein Handler kann später mit RemoveHandler entfernt werden. Der Listener wird aufgerufen, wenn das Ereignis ausgelöst wird.
val RemoveHandler: 'del → unit Entfernt einen Listener-Delegaten aus einem Ereignis-Listener-Speicher.

Der folgende Abschnitt enthält ein vollständiges Beispiel.

Beispiel

Das folgende Beispiel zeigt das oben diskutierte Konzept und die Techniken -

type Worker(name : string, shift : string) =
   let mutable _name = name;
   let mutable _shift = shift;

   let nameChanged = new Event<unit>() (* creates event *)
   let shiftChanged = new Event<unit>() (* creates event *)

   member this.NameChanged = nameChanged.Publish (* exposed event handler *)
   member this.ShiftChanged = shiftChanged.Publish (* exposed event handler *)

   member this.Name
      with get() = _name
      and set(value) = 
         _name <- value
         nameChanged.Trigger() (* invokes event handler *)

   member this.Shift
      with get() = _shift
      and set(value) = 
         _shift <- value
         shiftChanged.Trigger() (* invokes event handler *)

let wk = new Worker("Wilson", "Evening")
wk.NameChanged.Add(fun () -> printfn "Worker changed name! New name: %s" wk.Name)
wk.Name <- "William"
wk.NameChanged.Add(fun () -> printfn "-- Another handler attached to NameChanged!")
wk.Name <- "Bill"

wk.ShiftChanged.Add(fun () -> printfn "Worker changed shift! New shift: %s" wk.Shift)
wk.Shift <- "Morning"
wk.ShiftChanged.Add(fun () -> printfn "-- Another handler attached to ShiftChanged!")
wk.Shift <- "Night"

Wenn Sie das Programm kompilieren und ausführen, wird die folgende Ausgabe ausgegeben:

Worker changed name! New name: William
Worker changed name! New name: Bill
-- Another handler attached to NameChanged!
Worker changed shift! New shift: Morning
Worker changed shift! New shift: Night
-- Another handler attached to ShiftChanged!