0

最近、次のようなコードを持っている人が増えています。

private AsynchronousReader r;

public SynchronousReader()
{
    r = new AsynchronousReader();

    // My practice is to put this here
    // and then never remove it and never add it again
    // thus cleaning up the code and preventing constant add/remove.
    //r.ReadCompleted += this.ReadCompletedCallback;
}

private ReadCompletedCallback()
{
    // Remove the callback to "clean things up"...
    r.ReadCompleted -= this.ReadCompletedCallback;

    // Do other things
}

public Read()
{
    r.ReadCompleted += this.ReadCompletedCallback;

    // This call completes asynchronously and later invokes the above event
    r.ReadAsync();
    r.WaitForCompletion();
}

人々は、この方法は私が上で示した方法よりも優れていると言い、Silverlightに固有のいくつかの理由を挙げています。彼らはそれがメモリリーク、スレッドの問題を防ぎ、そしてそれが通常の慣行でさえあると述べています。

私はSilverlightをあまり行っていませんが、それでもこれを行うのはばかげているようです。コンストラクターでコールバックを一度だけリグアップする代わりに、オブジェクトの存続期間中にこのメソッドを使用する特定の理由はありますか?

これは私が例を作ることができるのと同じくらい簡単です。非同期オブジェクトを同期オブジェクトに変える一種のラッパーであるという事実を無視してください。イベントの追加と削除の方法にのみ興味があります。

4

2 に答える 2

1

あなたが言及した場合、それを一度接続すること理にかなっていますが、イベントハンドラーがまだそれらを参照しているため、オブジェクト(親および/または子)がガベージコレクションされない可能性があります。

ここのマークガベルによると

つまり、次の場合:

publisher.SomeEvent += target.SomeHandler;

その場合、「publisher」は「target」を存続させますが、「target」は「publisher」を存続させません。

覚えておくべきより重要なポイントは、子オブジェクトの寿命かもしれません。親と同じ場合は、コンストラクターでの1回限りのサブスクリプションの方が理にかなっています。動的な場合は、ハンドラーがリークするのを確認したので、ハンドラーを削除することをお勧めします(複数のコールバックが発生します)。

注:コンストラクターのみのメソッドでオブジェクトがリークすることが判明した場合は、いつでも購読解除を行うことができますが、Dispose()これまでに見たことがあるとは言えません。

于 2012-06-07T15:29:27.817 に答える
-1

2つの問題があるようです。

  1. 実際には1回だけ使用する必要があるオブジェクトを再利用しようとしています。
  2. そのオブジェクトは適切にクリーンアップする必要があります。

SynchronousReaderオブジェクトのインスタンスを1回だけ使用するか(したがって、他の場所で説明したように1つが終了しない2つの非同期呼び出しを回避する)、イベントのサブスクライブを解除してメモリリークを防ぐためにIDisposableを実装する必要があります。

3番目の解決策が可能かもしれません:SynchronousReaderの単一インスタンスを保持しますが、SynchronousReader.Readを呼び出すたびに、(インスタンス内のプライベートフィールドとして保存するのではなく)AsynchronousReaderの新しいインスタンスが作成されます。そうすれば、それより上では気に入らないが、イベントサブスクリプションを適切に処理するコードのほとんどを保持できます。

于 2012-06-07T16:03:24.103 に答える