F# - 事件



事件允許類之間相互發送和接收訊息。

在 GUI 中,事件是使用者操作,例如按鍵、點選、滑鼠移動等,或某些事件,例如系統生成的通知。應用程式需要在事件發生時做出響應。例如,中斷。事件用於程序間通訊。

物件透過同步訊息傳遞相互通訊。

事件附加到其他函式;物件將**回撥**函式註冊到事件,並且當(如果)某個物件觸發事件時,將執行這些回撥。

Event 類和 Event 模組

Control.Event<'T> 類有助於建立可觀察的物件或事件。

它具有以下例項成員來處理事件:

成員 描述
Publish 釋出觀察結果作為一等值。
Trigger 使用給定引數觸發觀察結果。

Control.Event 模組提供用於管理事件流的函式:

描述
add : ('T → unit) → Event<'Del,'T> → unit 每次觸發給定事件時都執行給定函式。
choose : ('T → 'U option) → IEvent<'Del,'T> → IEvent<'U> 返回一個新事件,該事件在從原始事件中選擇的訊息上觸發。選擇函式將原始訊息轉換為可選的新訊息。
filter : ('T → bool) → IEvent<'Del,'T> → IEvent<'T> 返回一個新事件,該事件偵聽原始事件,並且僅當事件的引數透過給定函式時才觸發結果事件。
map : ('T → 'U) → IEvent<'Del, 'T> → IEvent<'U> 返回一個新事件,該事件傳遞由給定函式轉換的值。
merge : IEvent<'Del1,'T> → IEvent<'Del2,'T> → IEvent<'T> 當任一輸入事件觸發時觸發輸出事件。
pairwise : IEvent<'Del,'T> → IEvent<'T * 'T> 返回一個新事件,該事件在輸入事件的第二次及後續觸發時觸發。輸入事件的第 **N** 次觸發將第 **N-1** 次和第 **N** 次觸發的引數作為對傳遞。傳遞給第 **N-1** 次觸發的引數將儲存在隱藏的內部狀態中,直到發生第 **N** 次觸發。
partition : ('T → bool) → IEvent<'Del,'T> → IEvent<'T> * IEvent<'T> 返回一個新事件,該事件偵聽原始事件,如果將謂詞應用於事件引數返回 true,則觸發第一個結果事件,如果返回 false,則觸發第二個事件。
scan : ('U → 'T → 'U) → 'U → IEvent<'Del,'T> → IEvent<'U> 返回一個新事件,該事件包含將給定的累積函式應用於輸入事件上觸發的連續值的結果。內部狀態的一個專案記錄狀態引數的當前值。在執行累積函式期間不會鎖定內部狀態,因此應注意輸入 IEvent 不要由多個執行緒同時觸發。
split : ('T → Choice<'U1,'U2>) → IEvent<'Del,'T> → IEvent<'U1> * IEvent<'U2> 返回一個新事件,該事件偵聽原始事件,如果將函式應用於事件引數返回 Choice1Of2,則觸發第一個結果事件,如果返回 Choice2Of2,則觸發第二個事件。

建立事件

事件透過 **Event** 類建立和使用。Event 建構函式用於建立事件。

示例

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

之後,您需要將 nameChanged 欄位公開為公共成員,以便偵聽器可以掛接到事件上,為此,您使用事件的 **Publish** 屬性:

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

接下來,您將回調新增到事件處理程式。每個事件處理程式都具有型別 IEvent<'T>,它提供了幾種方法:

方法描述
val Add : event:('T → unit) → unit 將偵聽器函式連線到事件。當事件觸發時,將呼叫偵聽器。
val AddHandler : 'del → unit 將處理程式委託物件連線到事件。稍後可以使用 RemoveHandler 刪除處理程式。當事件觸發時,將呼叫偵聽器。
val RemoveHandler : 'del → unit 從事件偵聽器儲存中刪除偵聽器委託。

以下部分提供了一個完整的示例。

示例

以下示例演示了上面討論的概念和技術:

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"

編譯並執行程式時,它會產生以下輸出:

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!
廣告

© . All rights reserved.