Do you need to assign the IDisposable returned by IObservable.Subscribe
to a variable in order to protect the subscription from being garbage collected, or is the presence of an active subscription enough?
My use case: I create a one-shot observable from an existing observable (myObservable
in the example):
myObservable.Take(1).Subscribe(fun v -> printfn "One-shot: %A" v) |> ignore
Yes, the presence of active subscription is enough. The GC-preventing chain of references to your subscription starts ultimately at the source of the very first observable, so while the stream source is alive, your subscription is also alive. If the stream source itself gets collected, then your subscription will die with it, but that's ok, because it wouldn't ever be invoked again anyway.
On the flip side, once your subscription receives one pulse, the .Take(1)
implementation will disconnect it from the source, allowing it to be collected.
In Rx.NET 2.2 there are no usages of Finalisers, so your subscription will never be disposed just because it got garbage collected.
If you do not assign the subscription to a variable and explicity dispose of it, it will continue to run until it terminates (OnComplete/OnError). This is outlined here - http://introtorx.com/Content/v1.0.10621.0/03_LifetimeManagement.html#Finalizers
Thus by not assigning the subscription to a variable, you loose the ability to Dispose of the subscription early. i.e. if a user wanted to cancel the action before a result was returned, you will have lost this ability.
An proof of this behaviour (in C#, sorry)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With