2016-03-25 19 views
4

あなたはごみを収集、または十分なアクティブなサブスクリプションの存在であることから、サブスクリプションを保護するために、変数にIObservable.Subscribeによって返さIDisposableを割り当てる必要がありますか?Rxのサブスクリプションとガベージコレクション

私のユースケース:私は(例ではmyObservable)既存の観測可能で、ワンショット、観察を作成します。

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

は今までソルバーUACについてのあなたの最後の質問を、あなたをしましたか? –

+0

いいえ、それは奇妙な底なしの穴でした。 –

答えて

5

はい、アクティブなサブスクリプションの存在は十分にあります。あなたのサブスクリプションへの参照のGC防止チェーンは、最初の観測可能なソースから最終的に始まります。ストリームソースは生きていますが、サブスクリプションも生きています。ストリームソース自体が収集された場合、サブスクリプションはそれで消滅しますが、それはもう一度呼び出されないため、正常です。フリップ側では

サブスクリプションは、1つのパルスを受信すると、.Take(1)実装は、それが収集できるように、ソースから外します。

2

Rx.NET 2.2では、ファイナライザは使用されていないため、サブスクリプションはガベージコレクションのために処分されることはありません。

あなたが変数にサブスクリプションを割り当て、明示的にそれを処分していない場合は、それが終了するまで実行し続けます(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. 
+0

私のアプリケーションでは問題はありませんが、シーケンスは1秒以内に完了するか、タイムアウトしますが、興味深い情報です。 –

+0

Cool。しかし、それは気づくべきことです。サブスクリプショントークンの無視を開始すると、滑りやすい斜面になる可能性があります。他の人はあなたのパターンに従うことができ、彼らがリソースを漏らしていることを認識しません。 –

関連する問題