Rx 订阅和垃圾回收

Rx subscriptions and garbage collection

您是否需要将 IObservable.Subscribe 返回的 IDisposable 分配给变量以保护订阅不被垃圾收集,或者是否存在活动订阅就足够了?

我的用例:我从现有的可观察对象(示例中的myObservable)创建了一个一次性可观察对象:

myObservable.Take(1).Subscribe(fun v -> printfn "One-shot: %A" v) |> ignore

是的,活跃订阅的存在就足够了。防止 GC 的订阅引用链最终从第一个可观察对象的源开始,因此当流源处于活动状态时,您的订阅也处于活动状态。如果流源本身被收集,那么您的订阅将随之消失,但这没关系,因为无论如何都不会再次调用它。

另一方面,一旦您的订阅收到一个脉冲,.Take(1) 实施将断开它与源的连接,以便收集它。

在 Rx.NET 2.2 中没有使用 Finalisers,所以您的订阅永远不会因为它被垃圾收集而被丢弃。

如果您不将订阅分配给变量并明确处置它,它将继续 运行 直到它终止 (OnComplete/OnError)。此处概述 - http://introtorx.com/Content/v1.0.10621.0/03_LifetimeManagement.html#Finalizers

因此,如果不将订阅分配给变量,您就失去了提前处理订阅的能力。也就是说,如果用户想在返回结果之前取消操作,您将失去这种能力。

此行为的证明(在 C# 中,抱歉)

var myObservable = Observable.Timer(TimeSpan.FromSeconds(1));
myObservable.Take(1).Subscribe(v => Console.WriteLine($"One-shot: {v}"));

//Force full GC.
GC.Collect();
//Wait for any Finalizers
GC.WaitForPendingFinalizers();
//Then clear out anything kept by finalizers.
GC.Collect();

//We will still see "One-shot: 0" written to the console.