F # - Eventi

Gli eventi consentono alle classi di inviare e ricevere messaggi tra loro.

Nella GUI, gli eventi sono azioni dell'utente come la pressione di un tasto, i clic, i movimenti del mouse, ecc. O alcuni eventi come le notifiche generate dal sistema. Le applicazioni devono rispondere agli eventi quando si verificano. Ad esempio, interrompe. Gli eventi vengono utilizzati per la comunicazione tra processi.

Gli oggetti comunicano tra loro tramite il passaggio di messaggi sincrono.

Gli eventi sono associati ad altre funzioni; registro oggetticallback funzioni a un evento e questi callback vengono eseguiti quando (e se) l'evento viene attivato da qualche oggetto.

La classe di eventi e il modulo di eventi

La classe Control.Event <'T> aiuta nella creazione di un oggetto o evento osservabile.

Ha i seguenti membri dell'istanza per lavorare con gli eventi:

Membro Descrizione
Pubblicare Pubblica un'osservazione come valore di prima classe.
Trigger Attiva un'osservazione utilizzando i parametri forniti.

Il modulo Control.Event fornisce funzioni per la gestione dei flussi di eventi:

Valore Descrizione
aggiungi: ('T → unit) → Event <' Del, 'T> → unit Esegue la funzione data ogni volta che viene attivato l'evento specificato.
scegli: (opzione 'T →' U) → IEvent <'Del,' T> → IEvent <'U> Restituisce un nuovo evento che si attiva su una selezione di messaggi dall'evento originale. La funzione di selezione trasforma un messaggio originale in un nuovo messaggio opzionale.
filtro: ('T → bool) → IEvent <' Del, 'T> → IEvent <' T> Restituisce un nuovo evento che ascolta l'evento originale e attiva l'evento risultante solo quando l'argomento dell'evento supera la funzione data.
mappa: ('T →' U) → IEvent <'Del,' T> → IEvent <'U> Restituisce un nuovo evento che passa i valori trasformati dalla funzione data.
unione: IEvent <'Del1,' T> → IEvent <'Del2,' T> → IEvent <'T> Genera l'evento di output quando uno degli eventi di input viene attivato.
pairwise: IEvent <'Del,' T> → IEvent <'T *' T> Restituisce un nuovo evento che si attiva alla seconda e successiva attivazione dell'evento di input. IlNth l'attivazione dell'evento di input passa gli argomenti dal file N-1th e Nthinnescando in coppia. L'argomento è passato alN-1th l'attivazione viene mantenuta in stato interno nascosto fino a quando il Nth si verifica il trigger.
partizione: ('T → bool) → IEvent <' Del, 'T> → IEvent <' T> * IEvent <'T> Restituisce un nuovo evento che ascolta l'evento originale e attiva il primo evento risultante se l'applicazione del predicato agli argomenti dell'evento ha restituito true e il secondo evento se ha restituito false.
scansione: ('U →' T → 'U) →' U → IEvent <'Del,' T> → IEvent <'U> Restituisce un nuovo evento costituito dai risultati dell'applicazione della funzione di accumulazione data a valori successivi attivati ​​sull'evento di input. Un elemento di stato interno registra il valore corrente del parametro di stato. Lo stato interno non è bloccato durante l'esecuzione della funzione di accumulazione, quindi è necessario fare attenzione che l'input IEvent non venga attivato da più thread contemporaneamente.
split: ('T → Choice <' U1, 'U2>) → IEvent <' Del, 'T> → IEvent <' U1> * IEvent <'U2> Restituisce un nuovo evento che ascolta l'evento originale e attiva il primo evento risultante se l'applicazione della funzione agli argomenti dell'evento ha restituito un Choice1Of2 e il secondo evento se restituisce un Choice2Of2.

Creazione di eventi

Gli eventi vengono creati e utilizzati tramite Eventclasse. Il costruttore di eventi viene utilizzato per creare un evento.

Esempio

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

Dopodiché devi esporre il campo nameChanged come membro pubblico, in modo che gli ascoltatori possano agganciarsi all'evento per il quale, usi il Publish proprietà dell'evento -

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 *)

Successivamente, aggiungi i callback ai gestori di eventi. Ogni gestore di eventi ha il tipo IEvent <'T>, che fornisce diversi metodi:

Metodo Descrizione
val Aggiungi: evento :( 'T → unit) → unit Collega una funzione listener all'evento. Il listener verrà richiamato quando l'evento viene attivato.
val AddHandler: 'del → unit Connette un oggetto delegato del gestore all'evento. Un gestore può essere successivamente rimosso utilizzando RemoveHandler. Il listener verrà richiamato quando l'evento viene attivato.
val RemoveHandler: 'del → unit Rimuove un delegato del listener da un archivio listener di eventi.

La sezione seguente fornisce un esempio completo.

Esempio

Il seguente esempio dimostra il concetto e le tecniche discusse sopra:

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"

Quando compili ed esegui il programma, restituisce il seguente output:

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!