在 F# 中,我知道如何使用 Async.AwaitEvent
异步等待一个事件:
let test = async {
let! move = Async.AwaitEvent(form.MouseMove)
...handle move... }
假设我想等待 MouseMove
或KeyDown
事件。我想要这样的东西:
let! moveOrKeyDown = Async.AwaitEvent(form.MouseMove, form.KeyDown)
这个函数不存在,但是还有其他方法吗?
最佳答案
我使用了您在talk about reactive programming中的示例中使用的方法的实现。我在伦敦拥有的(页面底部有一个下载链接)。如果您对这个主题感兴趣,您可能会发现这次演讲也很有用:-)。
我使用的版本采用 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
顺便说一句:您可能还想查看this article (基于我书中的第 16 章)。
关于events - 在 F# 中同时等待多个事件中的任何一个事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3701861/