F # - wydarzenia
Zdarzenia umożliwiają klasom wysyłanie i odbieranie wiadomości między sobą.
W graficznym interfejsie użytkownika zdarzenia to działania użytkownika, takie jak naciśnięcie klawisza, kliknięcia, ruchy myszą itp. Lub pewne zdarzenia, takie jak powiadomienia generowane przez system. Aplikacje muszą reagować na zdarzenia, gdy się pojawiają. Na przykład przerywa. Zdarzenia służą do komunikacji między procesami.
Obiekty komunikują się ze sobą poprzez synchroniczne przekazywanie wiadomości.
Wydarzenia są powiązane z innymi funkcjami; rejestr obiektówcallback funkcje do zdarzenia, a te wywołania zwrotne są wykonywane, gdy (i jeśli) zdarzenie jest wyzwalane przez jakiś obiekt.
Klasa zdarzenia i moduł zdarzeń
Klasa Control.Event <'T> pomaga w tworzeniu obserwowalnego obiektu lub zdarzenia.
Ma następujących członków instancji do pracy ze zdarzeniami:
Członek | Opis |
---|---|
Publikować | Publikuje obserwację jako wartość pierwszej klasy. |
Cyngiel | Uruchamia obserwację przy użyciu podanych parametrów. |
Moduł Control.Event zapewnia funkcje do zarządzania strumieniami zdarzeń -
Wartość | Opis |
---|---|
dodaj: ('T → jednostka) → Zdarzenie <' Del, 'T> → jednostka | Uruchamia daną funkcję za każdym razem, gdy zostanie wyzwolone dane zdarzenie. |
wybierz: (opcja 'T →' U) → IEvent <'Del,' T> → IEvent <'U> | Zwraca nowe zdarzenie uruchamiane na wybranych wiadomościach z pierwotnego zdarzenia. Funkcja wyboru przenosi oryginalną wiadomość do opcjonalnej nowej wiadomości. |
filter: ('T → bool) → IEvent <' Del, 'T> → IEvent <' T> | Zwraca nowe zdarzenie, które nasłuchuje pierwotnego zdarzenia i wyzwala wynikowe zdarzenie tylko wtedy, gdy argument zdarzenia przekazuje daną funkcję. |
mapa: ('T →' U) → IEvent <'Del,' T> → IEvent <'U> | Zwraca nowe zdarzenie, które przekazuje wartości przekształcone przez daną funkcję. |
scal: IEvent <'Del1,' T> → IEvent <'Del2,' T> → IEvent <'T> | Uruchamia zdarzenie wyjściowe, gdy jedno ze zdarzeń wejściowych zostanie wyzwolone. |
parami: IEvent <'Del,' T> → IEvent <'T *' T> | Zwraca nowe zdarzenie, które jest wyzwalane przy drugim i kolejnym wyzwoleniu zdarzenia wejściowego. PlikNth wyzwolenie zdarzenia wejściowego powoduje przekazanie argumentów z N-1th i Nthwyzwalanie jako para. Argument przekazany doN-1th wyzwalanie jest utrzymywane w ukrytym stanie wewnętrznym do momentu Nth następuje wyzwalanie. |
partycja: ('T → bool) → IEvent <' Del, 'T> → IEvent <' T> * IEvent <'T> | Zwraca nowe zdarzenie, które nasłuchuje pierwotnego zdarzenia i wyzwala pierwsze zdarzenie wynikowe, jeśli zastosowanie predykatu do argumentów zdarzenia zwróciło wartość true, a drugie zdarzenie, jeśli zwróciło wartość false. |
skanowanie: ('U →' T → 'U) →' U → IEvent <'Del,' T> → IEvent <'U> | Zwraca nowe zdarzenie składające się z wyników zastosowania danej funkcji sumującej do kolejnych wartości wyzwalanych w zdarzeniu wejściowym. Pozycja stanu wewnętrznego rejestruje bieżącą wartość parametru stanu. Stan wewnętrzny nie jest blokowany podczas wykonywania funkcji akumulacji, dlatego należy uważać, aby wejście IEvent nie było wyzwalane przez wiele wątków jednocześnie. |
split: ('T → Wybór <' U1, 'U2>) → IEvent <' Del, 'T> → IEvent <' U1> * IEvent <'U2> | Zwraca nowe zdarzenie, które nasłuchuje pierwotnego zdarzenia i wyzwala pierwsze zdarzenie wynikowe, jeśli zastosowanie funkcji do argumentów zdarzenia zwróciło Choice1Of2, a drugie zdarzenie, jeśli zwróci Choice2Of2. |
Tworzenie wydarzeń
Wydarzenia są tworzone i używane za pośrednictwem Eventklasa. Konstruktor Event służy do tworzenia zdarzenia.
Przykład
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
Następnie musisz ujawnić pole nameChanged jako publiczny element członkowski, aby nasłuchujący mogli podłączyć się do zdarzenia, dla którego użyjesz pola Publish własność imprezy -
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 *)
Następnie dodajesz wywołania zwrotne do programów obsługi zdarzeń. Każdy program obsługi zdarzeń ma typ IEvent <'T>, który udostępnia kilka metod -
metoda | Opis |
---|---|
val Dodaj: zdarzenie :( 'T → jednostka) → jednostka | Łączy funkcję detektora ze zdarzeniem. Odbiornik zostanie wywołany po uruchomieniu zdarzenia. |
val AddHandler: 'del → unit | Łączy obiekt delegata programu obsługi ze zdarzeniem. Program obsługi można później usunąć za pomocą RemoveHandler. Odbiornik zostanie wywołany po uruchomieniu zdarzenia. |
val RemoveHandler: 'del → unit | Usuwa delegata nasłuchiwania z magazynu nasłuchiwania zdarzeń. |
Poniższa sekcja zawiera pełny przykład.
Przykład
Poniższy przykład demonstruje koncepcję i techniki omówione powyżej -
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"
Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -
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!