F# - 活动

事件允许类在彼此之间发送和接收消息.

在GUI中,事件是用户操作,如按键,点击,鼠标移动等,或某些事件,如系统生成通知.应用程序需要在事件发生时对其进行响应.例如,中断.事件用于进程间通信.

对象通过同步消息传递相互通信.

事件附加到其他函数;对象向事件注册回调函数,并且当某个对象触发事件(以及如果)时执行这些回调.

事件类和事件模块

Control.Event<'T>类有助于创建可观察对象或事件.

它有以下实例成员来处理事件 :

会员描述
Publish将观察值作为第一类值发布.
Trigger使用给定参数触发观察.

Control.Event模块提供管理事件流的功能 :


描述

add : ('T &rarr; unit) &rarr;   Event<'Del,'T> &rarr; unit

每次触发给定事件时运行给定函数.

choose : ('T &rarr; 'U option) &rarr;   IEvent<'Del,'T> &rarr; IEvent<'U>

返回一个新事件,该事件触发原始事件中的一系列消息.选择函数将原始消息带到可选的新消息.

filter : ('T &rarr; bool) &rarr;   IEvent<'Del,'T> &rarr; IEvent<'T>

返回一个新事件,该事件侦听原始事件,并仅在事件的参数传递给定函数时触发结果事件.

map : ('T &rarr; 'U) &rarr; IEvent<'Del,   'T> &rarr; IEvent<'U>

返回一个新事件,它传递给定函数转换的值.

merge : IEvent<'Del1,'T> &rarr; IEvent<'Del2,'T>   &rarr; IEvent<'T>

在任何一个输入事件触发时触发输出事件.

pairwise : IEvent<'Del,'T> &rarr;   IEvent<'T * 'T>

返回在第二次和随后触发输入事件时触发的新事件Nth 触发输入事件会将 N-1th  Nth 中的参数作为一对触发.传递给 N-1th 触发的参数保持在隐藏的内部状态,直到 Nth 触发发生.

partition : ('T &rarr; bool) &rarr;   IEvent<'Del,'T> &rarr; IEvent<'T> * IEvent<'T>

返回一个新事件,该事件侦听原始事件并在事件参数的谓词应用程序返回true时触发第一个结果事件,并返回第二个事件如果它返回false.

scan : ('U &rarr; 'T &rarr; 'U) &rarr; 'U   &rarr; IEvent<'Del,'T> &rarr; IEvent<'U>

返回一个新事件,该事件由将给定累加函数应用于在输入事件上触发的连续值的结果组成.内部状态项记录状态参数的当前值.在执行累加功能期间内部状态未被锁定,因此应注意输入IEvent不是由多个线程同时触发的.

split : ('T &rarr; Choice<'U1,'U2>) &rarr;   IEvent<'Del,'T> &rarr; IEvent<'U1> * IEvent<'U2>

返回一个新事件,它侦听原始事件并触发第一个结果事件,如果函数的应用程序返回一个Choice1Of2,第二个如果它返回一个Choice2Of2的事件.

创建事件

创建事件并通过事件类使用. 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字段公开为公共成员,以便监听器可以挂钩事件,你使用事件的发布属性 :

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 &rarr; unit) &rarr; unit将侦听器函数连接到事件.触发事件时将调用侦听器.
val AddHandler : 'del &rarr; unit将处理程序委托对象连接到事件.稍后可以使用RemoveHandler删除处理程序.触发事件时将调用侦听器.
val RemoveHandler : 'del &rarr; 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!