Передача IDisposable в качестве параметра - PullRequest
6 голосов
/ 03 сентября 2011

Рекомендуется ли передавать 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 ]

5 голосов
/ 03 сентября 2011

Думаю, вам лучше взять делегата на создание, чтобы гарантировать удаление объекта.

* ** 1003 тысяча два * Пример
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
    }
}
2 голосов
/ 03 сентября 2011

Нет, владелец должен избавиться от него. Владельцем обычно является объект, создавший экземпляр IDisposable в первую очередь. Вы можете прочитать о лучших методах IDisposable здесь .

Утилизируйте все одноразовые поля, определенные в вашем типе. из вашего метода утилизации. Вы должны вызывать Dispose () для любых полей чей жизненный цикл контролирует ваш объект. Например, рассмотрим случай где ваш объект владеет частным полем TextReader. В вашем типе Dispose, вы должны вызвать Dispose объекта TextReader, который будет в свою очередь распоряжаться своими одноразовыми полями (Stream и Encoding, для пример) и тд. Если реализовано внутри Dispose (удаление bool) метод, это должно происходить, только если параметр размещения true - касание других управляемых объектов не допускается во время финализации. Кроме того, если вашему объекту не принадлежит данный одноразовый предмет, он не должен пытаться утилизировать его, как другие код все еще может полагаться на то, что он активен. Оба из них могут привести к обнаруживаемые ошибки.

Это может быть хорошей идеей для минимизации передачи IDisposable экземпляров, чтобы вам не приходилось слишком много думать о владельцах.

0 голосов
/ 03 сентября 2011

В любой момент времени от момента создания до вызова Dispose любой экземпляр IDisposable должен иметь ровно одного владельца, который будет отвечать за его удаление. Как правило, владельцем IDisposable будет объект, который его создал, но в некоторых случаях может быть полезно передать объекту владение IDisposable другому объекту. Рассмотрим, например, следующие два гипотетических класса:

  1. SoundSource, который реализует метод GetAudio, который возвращает следующие 'n' семплов звука. SoundSource реализует IDisposable, потому что его можно использовать для потоковой передачи звука из файла; если он не будет правильно удален, файл не закроется.
  2. AsyncSoundPlayer, который реализует метод PlaySound, который принимает SoundSource и запускает его воспроизведение, прерывая любой предыдущий воспроизводимый звук.

Во многих ситуациях подпрограмма, которая загружает SoundSource, на самом деле не будет заботиться о завершении воспроизведения; удобнее, когда подпрограмма воспроизведения становится владельцем SoundSource. Обратите внимание, что в некоторых случаях подпрограмма, которая запрашивает воспроизведение, может захотеть сохранить владение SoundSource. Наилучший подход состоит в том, чтобы предоставить средство, с помощью которого вызывающий объект может указать, желает ли он сохранить или передать право владения переданным идентификатором.

0 голосов
/ 03 сентября 2011

Это полностью зависит от вашей конкретной ситуации.

Как правило, «владелец» должен распоряжаться объектом, но ваша задача - выяснить, кто это. Это может быть не создатель, и он не может быть вызывающим в вашем случае.

...