5

最近、ReactiveExtensionsを使用するコードに小さなバグがあることに気づきました。タイマーを購読していましたが、購読を破棄しませんでした。これにより、メモリリークが発生しました。

この危険性を強調するスニペットを作成しました。

while (true)
{
    Observable.Timer(TimeSpan.Zero, TimeSpan.FromMinutes(1)).Subscribe(Console.WriteLine);
}

これは正常な動作ですか?

サブスクライバーがアプリの他の部分との接続を失ったときにタイマーをガベージコレクションするために、スケジューラーはタイマーへの弱参照を保持するべきではありませんか?

4

3 に答える 3

7

サブスクリプションへの参照を保持し、それらをと組み合わせることもできますが、それ以外の場合は無限の演算子(のような)でライフタイムCompositeDisposableを管理する通常の方法は、 (x値を取る)のような別の演算子に終了ルールを適用する演算子を使用することです。 ( trueを返しながら値を取得します)または(別のシーケンスyが値を発行するか、完了するまで値を取得します)。IObservableTimerTakeTakeWhilef(x)TakeUntil

実行中のRxオペレーターは、完了しない限り自動的にGCされません。Timer/ Interval、たとえば、両方を使用して次の値を再帰的にスケジュールしIScheduler、さまざまなスケジューラのデフォルトインスタンスはすべて、の静的プロパティを介してアクセスできますScheduler。これにより、実行中のオペレーターは常にルート化されるため、GCで使用できなくなります。

于 2011-06-06T06:48:05.723 に答える
4

これは正常であり、機能です

Subscribe()のセマンティクスは、永久にリッスンするか、Disposed()、OnCompleted()、またはOnError()のいずれか早い方までリッスンします。

于 2011-06-06T03:27:25.427 に答える
1

私はその答えに同意しません。無限ループを使用して連続するオブザーバブルを作成しているため、基本的に実行していることは冗長であり、したがってメモリリークが発生します。whileループを削除し、Observable.Timerを1つだけにするか、Observable.Intervalを使用することをお勧めします。1つのインスタンスだけで、それが不要になったときに、disposeを呼び出します。

于 2014-06-04T10:28:58.430 に答える