我试图理解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
这种行为与记录的行为有何不同?如果没有,那么为什么?
答案 0 :(得分:4)
timerEvent
的类型为Async<ElapsedEventArgs>
。通常,Async<'something>
只是您将来可能会重复运行的异步计算的表示。像let!
这样的结构就是Async<'something>
实际运行的方式。
这类似于let f() = printfn "wibble"
定义一个函数f
的方式,该函数将打印&#34; wibble&#34;每次运行。
所以,这里发生的是每次let! x = timerEvent
运行时,您再次订阅该活动并等待它发生。
一旦事件发生,该特定订阅将被取消,但控制将继续经过let!
到printfn
,然后再次循环并进行新订阅。