How to subscribe to events / observables poorly

I have a static event (publisher lifetime = application time) that I need to subscribe from views. I don't have a reliable definition of when a view moves away from it (the back navigation button pressed in Xamarin.Forms NavigationPage is one example), so I cannot determine when a view should unsubscribe from the observable. (I know that you can subscribe / unsubscribe to OnAppearing / OnDisappearing, but this has its own set of problems, which I will not dwell on here.)

Thus, I need the view to subscribe poorly to the event, i.e. Allow garbage collection without canceling an event subscription. Ideally, I would like something that can be used line by line myObj.myEvent |> Observable.AsWeak |> Observable.Subscribe ...or myObj.myEvent |> Observable.SubscribeWeakly ...or simply myObj.myEvent.SubscribeWeakly ....

Unfortunately, I do not know how to implement this. I heard about the System.WeakReference class , but for me it's not new at all, and I have no idea how to use it correctly - most of the examples I saw seem overly complicated for what I'm trying to do, which means that either I want something else, or there are still many pitfalls below the surface than I suspect.

How can I subscribe to events / observables in F #, allowing the subscriber to collect garbage without unsubscribing?

Similar but non-repeating questions:

+4
1

, , , , , , Code Review SE. Samuel Jack .NET, , 4 CodeProject #.

module Observable =
    open System

    // ('a -> 'b -> unit) -> 'a -> IObservable<'b>
    let subscribeWeakly callback target source = 

        let mutable sub:IDisposable = null
        let mutable disposed = false
        let wr = new WeakReference<_>(target)

        let dispose() =
            lock (sub) (fun () -> 
                if not disposed then sub.Dispose(); disposed <- true)

        let callback' x =
            let isAlive, target = wr.TryGetTarget()
            if isAlive then callback target x else dispose()

        sub <- Observable.subscribe callback' source
        sub

. WeakSubscriber.

!

me. this , , . ( ?), "" , let. ( private.)

:

type Publisher() =
    let myEvent = new Event<_>()
    [<CLIEvent>] member this.MyEvent = myEvent.Publish
    member this.Trigger(x) = myEvent.Trigger(x)


type StrongSubscriber() =

    member this.MyMethod x = 
        printfn "Strong: method received %A" x

    member this.Subscribe(publisher:Publisher) =
        publisher.MyEvent |> Observable.subscribe this.MyMethod
        publisher.MyEvent |> Observable.subscribe 
                             (fun x -> printfn "Strong: lambda received %A" x)


type WeakSubscriber() =

    member this.MyMethod x = 
        printfn "Weak: method received %A" x

    member this.Subscribe(publisher:Publisher) =
        publisher.MyEvent |> Observable.subscribeWeakly
                             (fun (me:WeakSubscriber) x -> me.MyMethod x) this
        publisher.MyEvent |> Observable.subscribeWeakly
                             (fun _ x -> printfn "Weak: lambda received %A" x) this

:

[<EntryPoint>]
let main argv = 

    let pub = Publisher()

    let doGc() =
        System.GC.Collect()
        System.GC.WaitForPendingFinalizers()
        System.GC.Collect()
        printfn "\nGC completed\n"

    let someScope() =
        let strong = StrongSubscriber()
        let weak = WeakSubscriber()
        strong.Subscribe(pub)
        weak.Subscribe(pub)

        doGc() // should not remove weak subscription since it still in scope
        printfn "All subscribers should still be triggered:"
        pub.Trigger(1)

    someScope()

    doGc() // should remove weak subscriptions
    printfn "Weak subscribers should not be triggered:"
    pub.Trigger(2)

    System.Console.ReadKey() |> ignore

    0

:

GC completed

All subscribers should still be triggered:
Strong: method received 1
Strong: lambda received 1
Weak: method received 1
Weak: lambda received 1

GC completed

Weak subscribers should not be triggered:
Strong: method received 2
Strong: lambda received 2
+2

Source: https://habr.com/ru/post/1684543/


All Articles