在 F# 中,我知道如何使用异步等待一个事件Async.AwaitEvent:
let test = async {
let! move = Async.AwaitEvent(form.MouseMove)
...handle move... }
假设我想等待MouseMove or the KeyDown事件。我想要这样的东西:
let! moveOrKeyDown = Async.AwaitEvent(form.MouseMove, form.KeyDown)
这个功能不存在,但是有其他方法可以做到这一点吗?
我使用了您在示例中使用的方法的实现谈论反应式编程我在伦敦拥有的(页面底部有一个下载链接)。如果您对这个主题感兴趣,您可能会发现这次演讲也很有用:-)。
我正在使用的版本需要IObservable
代替IEvent
(所以该方法的名称是AwaitObservable
)。有一些严重内存泄漏使用时Event.merge
(以及来自的其他组合器Event
模块)连同AwaitEvent
,所以你应该使用Observable.merge
等等以及AwaitObservable
反而。
问题描述的更详细here(参见第 3 节以获得清晰的示例)。简而言之 - 当您使用Event.merge
,它将一个处理程序附加到源事件(例如MouseDown
),但在您完成等待后,它不会删除处理程序AwaitEvent
,因此该事件永远不会被删除 - 如果您在使用异步工作流程编码的循环中继续等待,您将不断添加新的处理程序(在运行时不执行任何操作)。
一个简单的正确解决方案(基于什么desco发布)看起来像这样:
let rec loop () = async {
let e1 = f.KeyDown |> Observable.map Choice1Of2
let e2 = f.MouseMove |> Observable.map Choice2Of2
let! evt = Observable.merge e1 e2 |> Async.AwaitObservable
// ...
return! loop() } // Continue looping
顺便说一句:您可能还想看看本文(基于我书中的第 16 章)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)