Вопрос

Я отправляю поток методам для записи, и в этих методах я использую двоичный модуль чтения/записи.Когда читатель/писатель избавляется, либо using или просто когда на него нет ссылки, поток тоже закрывается??

Я бы отправил BinaryReader/Writer, но я тоже использую StreamReader (возможно, мне следует обойти это.Я использую это только для GetLine и ReadLine).Это довольно проблематично, если поток закрывается каждый раз, когда закрывается писатель/читатель.

Это было полезно?

Решение

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

Лично я предпочитаю использовать оператор использования и для потока.Вы можете вложить using утверждения без фигурных скобок довольно аккуратно:

using (Stream stream = ...)
using (StreamReader reader = new StreamReader(stream, Encoding.Whatever))
{
}

Несмотря на то, что using оператор для потока несколько избыточен (если только StreamReader конструктор выдает исключение) Я считаю это лучшей практикой, так как тогда, если вы избавитесь от StreamReader и просто используйте поток напрямую позже, у вас уже будет правильная семантика удаления.

Другие советы

Это старый вариант, но сегодня я хотел сделать что-то подобное и обнаружил, что все изменилось.Начиная с .net 4.5, существует leaveOpen аргумент:

public StreamReader( Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool leaveOpen )

Единственная проблема в том, что не совсем очевидно, что устанавливать для остальных параметров.Вот некоторая помощь:

От страница MSDN для конструктора StreamReader (поток):

Этот конструктор инициализирует кодирование в UTF8Coding, свойство Beadestream с использованием параметра потока и размер внутреннего буфера до 1024 байт.

Это просто оставляет detectEncodingFromByteOrderMarks что, судя по исходный код является true

public StreamReader(Stream stream)
        : this(stream, true) {
}

public StreamReader(Stream stream, bool detectEncodingFromByteOrderMarks)
        : this(stream, Encoding.UTF8, detectEncodingFromByteOrderMarks, DefaultBufferSize) {
}

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

Да, это так.Вы можете убедиться в этом, посмотрев реализацию с помощью Reflector.

protected override void Dispose(bool disposing)
{
    try
    {
        if ((this.Closable && disposing) && (this.stream != null))
        {
            this.stream.Close();
        }
    }
    finally
    {
        if (this.Closable && (this.stream != null))
        {    
            this.stream = null;    
            this.encoding = null;
            this.decoder = null;
            this.byteBuffer = null;
            this.charBuffer = null;
            this.charPos = 0;
            this.charLen = 0;
            base.Dispose(disposing);
        }
    }
}

Шесть лет спустя, но, возможно, это кому-то поможет.

StreamReader закрывает соединение при его удалении.Однако «использование (Streamstream = ...){...}» с StreamReader/StreamWriter может привести к тому, что поток будет удален дважды:(1) когда объект StreamReader удаляется (2) и когда блок Stream using закрывается.Это приводит к появлению предупреждения CA2202 при запуске анализа кода VS.

Другое решение, взятое непосредственно из CA2202 page, заключается в использовании блока try/finally.Настройте правильно, соединение будет закрыто только один раз.

Около нижней части CA2202, Microsoft рекомендует использовать следующее:

Stream stream = null;
try
{
    stream = new FileStream("file.txt", FileMode.OpenOrCreate);
    using (StreamWriter writer = new StreamWriter(stream))
    {
        stream = null;
        // Use the writer object...
    }
}
finally
{
    if(stream != null)
        stream.Dispose();
}

вместо...

// Generates a CA2202 warning
using (Stream stream = new FileStream("file.txt", FileMode.Open))
using (XmlReader reader = new XmlReader (stream))
{
    // Use the reader object...
}

Да.Вызов Dispose() и IDisposable (что и делает «использование») должен заставить объект очистить все свои ресурсы.Это включает в себя очистку потоков и закрытие их файловых дескрипторов.

Если в вашем случае вы хотите передать его другим методам, вам необходимо убедиться, что эти методы не выполняют чтение/запись в блоке использования.

Если вам нужно, простой способ исправить это — переопределить метод Dispose классов StreamWriter.Смотрите мой пост здесь, чтобы узнать, как это сделать:

Закрывает ли .Dispositing StreamWriter базовый поток?

поток удаляется либо с помощью ключевого слова «using», либо путем явного вызова

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top