Можно ли не закрывать StreamReader / StreamWriter, чтобы оставить основной поток открытым? - PullRequest
17 голосов
/ 17 декабря 2010

У меня есть класс, который по существу оборачивает поток для чтения / записи, но ожидается, что этим потоком будет управлять потребитель этого класса. Для простоты использования я использую классы StreamReader и StreamWriter для выполнения операций ввода-вывода в потоке. Обычно я бы обернул читателя и писателя в блоки using, но я хочу избежать закрытия читателя и писателя, потому что это также закрывает основной поток, и я должен держать его открытым.

Безопасно ли с точки зрения управления памятью / ресурсами не закрывать StreamReader / StreamWriter, если я ожидаю, что вызывающий будет управлять базовым потоком? Будет ли читатель и писатель собирать мусор, когда поток явно закрыт в другом месте?

public class Wrapper 
{
    private Stream _underlyingStream;
    public Wrapper(Stream underlyingStream) 
    {
        _underlyingStream = underlyingStream;
    }

    public string GetValue() 
    {
        _underlyingStream.Seek(0, SeekOrigin.Begin);
        var reader = new StreamReader(_underlyingStream);
        return reader.ReadToEnd(); // we're done, but the stream is not ours to close
    }
}

Ответы [ 3 ]

4 голосов
/ 17 декабря 2010

Если никто не закрывает потоки, то в конечном итоге будет вызван финализатор, который должен вызвать dispose и закрыть их после GC. Но это довольно дурацкий ресурс, потому что он оставляет любые, возможно, дорогостоящие ресурсы, выделенные до GC. Чем дольше живет ваш объект, тем хуже он может стать, особенно если он выживет в коллекциях для повышения до 1-го или даже 2-го поколения.

Было бы неплохо, если бы вы могли представить вызывающей стороне что-то, что изолирует это. Возможно, вы можете кэшировать что-то из потока, чтобы вы могли закрыть его, продолжая передавать контент вызывающей стороне?

РЕДАКТИРОВАТЬ после того, как вы отредактировали: Теперь, когда я вижу, что ваш вызывающий абонент ПРОХОДИТ вам поток для обработки, мой ответ должен быть другим! Совершенно очевидно, что ваш абонент должен управлять временем жизни потока. Сначала у меня сложилось впечатление, что ваш класс создал поток, и надеялся, что звонящий справится с этим.

1 голос
/ 17 декабря 2010

Самый простой способ решить эту проблему - заключить поток в свой собственный класс, производный от System.IO.Stream

Пример: http://csharptest.net/browse/src/Library/IO/NonClosingStream.cs

0 голосов
/ 17 декабря 2010

Это определенно не хорошо. читать это из MSDN

Закрытие вызывает метод Dispose, передавая истинное значение. Очистка потока не очистит его основной кодер, если вы явно не вызовете Close.

Попробуйте инкапсулировать все IO в классе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...