Yes, I think this is By Design. Change "Event.filter" to "Observable.filter" and then you get the desired behavior. I think perhaps this is one of the main advantages of observables over events - the various combinator patterns are more well-behaved (no leaking listeners).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
 

open System
open System.Reflection 

// from <A href="http://stackoverflow.com/questions/2111045/how-to-check-if-an-event-is-being-handled-in-f">http://stackoverflow.com/questions/2111045/how-to-check-if-an-event-is-being-handled-in-f</A>
type EventEx<'Delegate,'Args when 'Delegate : delegate<'Args,unit> and 'Delegate :> System.Delegate >() =  
        let mutable multicast : System.Delegate = null 
        static let argTypes =  
            let instanceBindingFlags = BindingFlags.Instance ||| BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.DeclaredOnly 
            let mi = typeof<'Delegate>.GetMethod("Invoke",instanceBindingFlags) 
            mi.GetParameters() |> (fun arr -> arr.[1..]) |> Array.map (fun p -> p.ParameterType) 
 
        member x.Handled = (multicast <> null) 
 
        member x.Trigger(sender:obj,args:'Args) =  
            match multicast with  
            | null -> () 
            | d ->  
                if argTypes.Length = 1 then  
                    d.DynamicInvoke([| sender; box args |]) |> ignore 
                else 
                    d.DynamicInvoke(Array.append [| sender |] (Microsoft.FSharp.Reflection.FSharpValue.GetTupleFields(box args))) |> ignore 
        member x.Publish =  
            { new IEvent<'Delegate,'Args> with  
                member x.AddHandler(d) = 
                    multicast <- System.Delegate.Combine(multicast, d) 
                member x.RemoveHandler(d) =  
                    multicast <- System.Delegate.Remove(multicast, d)  
                member e.Subscribe(observer) =  
                   let h = new Handler<_>(fun sender args -> observer.OnNext(args)) 
                   (e :?> IEvent<_,_>).AddHandler(h) 
                   { new System.IDisposable with  
                        member x.Dispose() = (e :?> IEvent<_,_>).RemoveHandler(h) } } 

let G() =
    printfn "Start G"
    let ev = new EventEx<Handler<unit>,unit>()
    let eventX = ev.Publish 
    printfn "%A" ev.Handled 

//    let sub2 = eventX |> Event.filter(fun p -> true) |> Observable.subscribe(fun _ -> Console.WriteLine("Hello")) 
    let sub2 = eventX |> Observable.filter(fun p -> true) |> Observable.subscribe(fun _ -> Console.WriteLine("Hello")) 
    ev.Trigger(null, ())
    printfn "%A" ev.Handled 
    sub2.Dispose() 
    printfn "%A" ev.Handled 
    printfn "Done G"
    
G()    

By on 1/26/2010 1:38 PM ()

Thank you very much.

I looked at the code for the Event implementation but not for Observable. Using Observable.filter no leaks occur.

GREAT :)

By on 1/26/2010 9:08 PM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper