8

IDisposableをパラメーターとしてメソッドに渡し、そのメソッド内に配置することをお勧めしますか。複数のスレッドを使用する必要がある場合、これは一種の避けられないことです。ベストプラクティスでは、所有者(発信者)がそれを破棄する必要があるとされています。

例えば

public void MyMethod(MyClass reader){
    using(reader){
        //some code
    }
}

所有者(スレッドを作成している)がもう存在しない場合はどうなりますか?例えば

interface IReader : IDisposable {
    string Read();
}

public class MyReader : IReader {

    public string Read()
    {
        return "hellow world";
    }
    public void Dispose()
    {
        //dispose code
    }
}

ここに問題があります...

public void Start() {
    MyReader[] readerSet = new MyReader[5];
    for (int i = 0; i < readerSet.Length; i++) {
        readerSet[i] = new MyReader();
    }
    foreach (IReader reader in readerSet) {
        ThreadPool.QueueUserWorkItem(new WaitCallback(Run), reader);
    }
    //exit after creating threads
}


public void Run(Object objReader) {
    IReader reader = (IReader)objReader;
    using (reader) { 
    //use the reader
    }
}
4

4 に答える 4

6

オブジェクトの廃棄を保証するために、作成デリゲートを使用する方がよいと思います。

public void Start() {
    var makeReader = new Func<IReader>(() => new MyReader()); 
    for (int i = 0; i < 5; i++) {
        ThreadPool.QueueUserWorkItem(Run, makeReader);
    }
}    

public void Run(Object state) {
    var makeReader = (Func<IReader>)state;
    using (var reader = makeReader()) { 
        //use the reader
    }
}
于 2011-09-02T22:52:52.223 に答える
3

いいえ、所有者はそれを処分する必要があります。所有者は通常、最初にIDisposableインスタンスを作成したオブジェクトです。IDisposableのベストプラクティスについては、こちらをご覧ください。

タイプで定義された使い捨てフィールドをDisposeメソッドから推移的に破棄します。オブジェクトがライフサイクルを制御するすべてのフィールドでDispose()を呼び出す必要があります。たとえば、オブジェクトがプライベートTextReaderフィールドを所有している場合を考えてみます。タイプのDisposeでは、TextReaderオブジェクトのDisposeを呼び出す必要があります。これにより、使い捨てフィールド(StreamやEncodingなど)が破棄されます。Dispose(bool disposed)メソッド内に実装されている場合、これは、disposedパラメーターがtrueの場合にのみ発生します。ファイナライズ中に他の管理対象オブジェクトに触れることは許可されていません。さらに、オブジェクトが特定の使い捨てオブジェクトを所有していない場合、他のコードがまだアクティブであることに依存している可能性があるため、オブジェクトを破棄しようとしないでください。これらは両方とも、微妙に検出できるバグにつながる可能性があります。

IDisposableインスタンスの受け渡しを最小限に抑えて、所有者についてあまり考える必要がないようにすることをお勧めします。

于 2011-09-02T22:46:56.963 に答える
0

IDisposableの作成から破棄呼び出しまでの任意の時点で、IDisposableのインスタンスには、削除を担当する所有者が1人だけいる必要があります。通常、IDisposableの所有者はそれを作成したエンティティですが、IDisposableの所有権を別のオブジェクトに譲渡することが役立つ場合があります。たとえば、次の2つの架空のクラスについて考えてみます。

  1. SoundSource。サウンドの次の「n」サンプルを返すGetAudioメソッドを実装します。SoundSourceは、ファイルからオーディオをストリーミングするために使用できるため、IDisposableを実装しています。適切に廃棄されていない場合、ファイルは閉じられません。
  2. AsyncSoundPlayerは、SoundSourceを受け入れて再生を開始し、以前の再生中のサウンドを中止するPlaySoundメソッドを実装します。

多くの場合、SoundSourceをロードするルーチンは、再生が完了したときに実際には気にしません。再生ルーチンにSoundSourceの所有権を持たせる方が便利な傾向があります。場合によっては、再生を要求するルーチンがSoundSourceの所有権を保持したい場合があることに注意してください。最良のアプローチは、ルーチンの呼び出し元が、渡されたIDisposableの所有権を保持するか渡すかを指定できる手段を許可することです。

于 2011-09-03T02:35:16.557 に答える
0

それは完全にあなたの特定の状況に依存します。

通常、「所有者」はオブジェクトを破棄する必要がありますが、それが誰であるかを把握するのはあなたの仕事です。それは作成者ではないかもしれませんし、あなたの場合も発信者ではないかもしれません。

于 2011-09-02T22:51:11.030 に答える