在调用基础事件后,Async.AwaitEvent不会取消

时间:2014-06-19 21:45:30

标签: .net events asynchronous f#

我试图理解Async.AwaitEvent行为。根据文件:

  

创建一个异步计算,通过向事件添加处理程序来等待CLI事件的单个调用。计算完成或取消后,处理程序将从事件中删除。

并从备注部分:

  

计算将在等待事件时响应取消。如果发生取消,并且指定了cancelAction,则执行取消,并且计算继续等待该事件。如果未指定cancelAction,则取消会导致计算立即取消。

我没有指定任何类型的取消操作,因此我希望该事件将被处理一次,并且一旦发生这种情况,处理程序应该被取消订阅。但是,如果我运行此示例,我可以看到该事件一次又一次地处理。

open Microsoft.FSharp.Control

let timer = new System.Timers.Timer(2000.0)
timer.AutoReset <- true
timer.Start()

let fn = async {
    let timerEvent = Async.AwaitEvent timer.Elapsed

    for _ in [1..10] do
        let! x = timerEvent
        printfn "elapsed event occurred at %O" x.SignalTime
}

fn |> Async.RunSynchronously

输出:

elapsed event occurred at 19.06.2014 23:46:21
elapsed event occurred at 19.06.2014 23:46:23
elapsed event occurred at 19.06.2014 23:46:25
elapsed event occurred at 19.06.2014 23:46:27
elapsed event occurred at 19.06.2014 23:46:29
elapsed event occurred at 19.06.2014 23:46:31
elapsed event occurred at 19.06.2014 23:46:33
elapsed event occurred at 19.06.2014 23:46:35
elapsed event occurred at 19.06.2014 23:46:37
elapsed event occurred at 19.06.2014 23:46:39

这种行为与记录的行为有何不同?如果没有,那么为什么?

1 个答案:

答案 0 :(得分:4)

timerEvent的类型为Async<ElapsedEventArgs>。通常,Async<'something>只是您将来可能会重复运行的异步计算的表示。像let!这样的结构就是Async<'something>实际运行的方式。

这类似于let f() = printfn "wibble"定义一个函数f的方式,该函数将打印&#34; wibble&#34;每次运行。

所以,这里发生的是每次let! x = timerEvent运行时,您再次订阅该活动并等待它发生。

一旦事件发生,该特定订阅将被取消,但控制将继续经过let!printfn,然后再次循环并进行新订阅。