Um zu verstehen, was los ist, habe ich den Quellcode nach Event.map, Event.merge und Choice gesucht.
type Choice<'T1,'T2> =
| Choice1Of2 of 'T1
| Choice2Of2 of 'T2
[<CompiledName("Map")>]
let map f (w: IEvent<'Delegate,'T>) =
let ev = new Event<_>()
w.Add(fun x -> ev.Trigger(f x));
ev.Publish
[<CompiledName("Merge")>]
let merge (w1: IEvent<'Del1,'T>) (w2: IEvent<'Del2,'T>) =
let ev = new Event<_>()
w1.Add(fun x -> ev.Trigger(x));
w2.Add(fun x -> ev.Trigger(x));
ev.Publish
Dies bedeutet, dass unsere Lösung 3 neue Ereignisse erstellt.
Wir könnten dies auf ein Ereignis reduzieren, indem wir eine eng gekoppelte Version dieses Bibliothekscodes erstellen.
type EventChoice<'T1, 'T2> =
| EventChoice1Of2 of 'T1
| EventChoice2Of2 of 'T2
with
static member CreateChoice (w1: IEvent<_,'T1>) (w2: IEvent<_,'T2>) =
let ev = new Event<_>()
w1.Add(fun x -> ev.Trigger(EventChoice1Of2 x))
w2.Add(fun x -> ev.Trigger(EventChoice2Of2 x))
ev.Publish
Und hier ist unser neuer Code.
async {
let merged = EventChoice.CreateChoice form.MouseMove form.KeyDown
let! move = Async.AwaitEvent merged
}
Vorsicht! Wenn Sie Ereignisse verwenden, die mit 'Event.xyz'-Kombinatoren zusammen mit' AwaitEvent' und 'let!' Erstellt wurden, können Sie ein Speicherleck erstellen (wenn Sie in einer Schleife warten). Sie ** sollten ** immer 'Observable' anstelle von' Event' verwenden, wenn Sie Kombinatoren mit asynchronen Workflows kombinieren möchten. Sehen Sie meine Antwort für weitere Details ... –