Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Events 如何弱订阅事件/观测值_Events_F#_Observable_Weak References - Fatal编程技术网

Events 如何弱订阅事件/观测值

Events 如何弱订阅事件/观测值,events,f#,observable,weak-references,Events,F#,Observable,Weak References,我需要从视图订阅一个类似静态(发布者生存期=应用程序生存期)的事件。我无法可靠地确定视图何时被导航离开(Xamarin.Forms NavigationPage中按下的navbar back按钮就是一个例子),因此我无法确定视图何时应该从observable取消订阅。(我知道在OnAppearing/OnDisappearing中订阅/取消订阅是可能的,但这也带来了一系列问题,我在这里不详细介绍。) 因此,我发现自己需要视图弱订阅事件,即允许视图被垃圾收集而不必取消订阅事件。理想情况下,我想要的

我需要从视图订阅一个类似静态(发布者生存期=应用程序生存期)的事件。我无法可靠地确定视图何时被导航离开(Xamarin.Forms NavigationPage中按下的navbar back按钮就是一个例子),因此我无法确定视图何时应该从observable取消订阅。(我知道在OnAppearing/OnDisappearing中订阅/取消订阅是可能的,但这也带来了一系列问题,我在这里不详细介绍。)

因此,我发现自己需要视图弱订阅事件,即允许视图被垃圾收集而不必取消订阅事件。理想情况下,我想要的东西可以按照
myObj.myEvent |>Observable.AsWeak |>Observable.Subscribe…
,或者
myObj.myEvent |>Observable.subscribebevely…
,或者简单地
myObj.myEvent.subscribebevent…

不幸的是,我不知道如何实现这一点。我听说过这门课,但这对我来说是全新的,我不知道如何正确地使用它——我所看到的大多数例子对于我试图做的事情来说似乎过于复杂,这意味着要么我想要一些不同的东西,要么表面下的陷阱比我想象的要多得多

我如何在F#中订阅事件/观察对象,同时允许订阅方在不取消订阅的情况下进行垃圾收集

类似但不重复的问题:

  • 问题是在F#中是否需要弱引用,而不是如何实现上述功能。这个问题的唯一答案在这方面也没有帮助

我已经找到了一个相对简单的函数,它似乎可以正常工作,尽管我真的不知道我在做什么,所以我把它放在了网站上。它基于Samuel Jack的信息以及CodeProject中的解决方案4

实施 实际测试:

[<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's 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

你不能直接“重写OnParentSet()”和“if(Parent==null)”在那里取消订阅吗。只要点击“后退”按钮弹出页面时,视图从屏幕上移除/就像父视图一样,它就会一直被调用。这很简单,但感谢您的提示。(顺便说一句,OnAppearing的主要问题是,在iOS上,它是在视图完全出现后调用的。)@Funk的可能重复在发布之前,我读了好几遍这个问题及其答案,但没有帮助,也不是重复。我已经更新了这个问题来解释这一点。如果你把它作为一个一般的.NET问题来处理,并把你发现的任何东西翻译成F#,可能会有所帮助。我在这里没有现成的答案,但有一种被很好地描述的模式(在WPF中使用)是使用中介
WeakEventManager
(请参阅)。如果Xamarin已经有了相应的解决方案,我不会感到惊讶。
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's 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