2016-08-09 8 views
0

私は(明らかに、彼は新しいアイテムに加入して、いくつかのサーバからアイテムをリロードするために、私はクラス回収が再開される前に、廃棄可能な廃棄物を処分する必要がありますか?

class B { 
    IEnumerable<A> Items { get; } 

    void Refresh() { 
     Items = GetNewListWithNewJustCreatedInstances(); 
    } 
} 

ユーザーが、その後、彼は最新の情報に更新を(呼び出して、多くの項目に複数回サブスクライブしていたクラス

class A { 
    IObservable<long> poll = new Observable.Interval(100 ms).Do((ms) => LoadData()); 

    void Subscribe() { 
     poll.Subscribe(); 
    } 
} 

)を持っています再び)。古いサブスクリプションはすべて自動的に破棄されるのですか、それともこのような実装が必要ですか?

class A : IDisposable { 
    void Dispose() { 
     poll.Dispose(); 
    } 
} 

class B { 
    void Refresh() { 
     foreach (var item in Items) { 
      item.Dispose(); 
     } 
    } 
} 
+2

ここで修正しようとしている特定の問題がない場合は、ガベージコレクタにそのジョブを実行させてください。 –

+1

@EdPlunkett問題を解決しようとしていません。Refresh()メソッドを実行した後にタイマーが毎回100ミリ秒実行されることが心配です。リフレッシュするたびに。私は** **アイテム**を処理していないので、**新しい**アイテムでコレクションを再作成して再作成します(ユーザーが古いアイテムを参照していれば、それは生きていると思います)。 – EwanCoder

+0

これは簡単にテストできるはずです。それが発射を続けるならば...ええ、あなたはそれらをスワットする必要があるでしょう。 –

答えて

0

あなたのコードは、複数のメモリリークのためのレシピです。 similar questionを参照してください。

Rxサブスクリプションは、処分されるまで永遠に生き続けるか、OnCompleteが呼び出されるかOnErrorになります。ガベージコレクションはそれらをクリーンアップしません。あなたは処分していないので、Observable.Intervalは完了しません。メモリが足りなくなるまで、各サブスクリプションはリークします。あなたのコードでは、Aのインスタンスごとに複数のサブスクリプションが可能で、明らかに複数のAオブジェクトが残っています。ここで

はそれをテストするためにいくつかのLinqpad優しいコードです:

void Main() 
{ 
    var a0 = new A(); 
    a0.Subscribe(); 
    a0.Subscribe(); 
    a0.Subscribe(); 
    a0.Dispose(); 
    a0 = null; 

    GC.Collect(); //Has no effect. Demonstrates Garbage collection doesn't help. 
} 

class A : IDisposable 
{ 
    IObservable<long> poll = Observable.Interval(TimeSpan.FromMilliseconds(100)).Do(l => l.Dump()); 
    IDisposable disposable; 
    public void Subscribe() 
    { 
     Dispose(); 
     //memory leak!! 
     poll.Subscribe(); 

     //Use this instead 
      //disposable = poll.Subscribe(); 
    } 

    public void Dispose() 
    { 
     disposable?.Dispose(); 
    } 
} 

メモリリークする行がコメント解除され、かつ安全な1がコメントし、あなたは3つの数字が間隔ごとに飛び出して表示されます、のための1つの場合には各サブスクリプション。使い捨て追跡ラインのコメントが外され、メモリリークがコメントアウトされると、出力が表示されません。

+0

問題はクラスAのインスタンスではありません。問題はサブスクリプションのインスタンスです。 'poll.Subscribe'がゴミとして収集されないオブジェクトを返すことを想像してみましょう。なぜなら、' Dispose'だけでチャプターをつけられる強い参照を持つミステリーな内部クラスがあるからです。したがって、あなたのシナリオでは、ガベージコレクションでは 'A'インスタンスはクリーンアップできますが、サブスクリプションインスタンスはクリーンアップされている可能性があります。 – Shlomo

+0

@EwanCoder - GC **は決して '.Dispose()'を呼び出しません。唯一の(ソート)例外は、あなたが明示的に '.Dispose()'を呼んでいることを知っているファイナライザが存在し、この**がGCによって呼び出される可能性がある場合です。 Rx購読**はファイナライザを持っていないので、GCはあなたのためにそれを処分しません。 – Enigmativity

関連する問題