System.ObjectDisposedException используя Using

137
24 октября 2019, 22:20

Интересная ситуация, кто объяснит такой феномен, используя Using для реализации Idisposable

private string GetWhoIs(string whoisServer, string ipAddr)
{
    StringBuilder stringBuilderResult = new StringBuilder();            
    using (TcpClient tcpClinetWhois = new TcpClient(whoisServer, 80))
    {
        using (NetworkStream networkStreamWhois = tcpClinetWhois.GetStream())
        {
            using (BufferedStream bufferedStreamWhois = new BufferedStream(networkStreamWhois))
            {
                using (StreamWriter streamWriter = new StreamWriter(bufferedStreamWhois))
                {
                    streamWriter.WriteLine(ipAddr);
                    streamWriter.Flush();
                    using (StreamReader streamReaderReceive = new StreamReader(bufferedStreamWhois))
                    {
                        while (!streamReaderReceive.EndOfStream)
                            stringBuilderResult.AppendLine(streamReaderReceive.ReadLine());
                    }
              **}**
            }
        }
    }
    return stringBuilderResult.ToString();
}

На выделенной строке происходит вызов исключения. На картинке

Не понимаю, что и как происходит закрытие потока. Что-то не то со Streamreader мое предположение. Спасибо

Answer 1

Конструкторы StreamReader/StreamWriter с одним параметром выставляют приватное свойство LeaveOpen в false. Это значит, что когда вы диспозите их экземпляры, то они диспозят и внутренний поток.

Здесь бы не было проблемы, так как по канонам Microsoft все IDisposable должны поддерживать вызов Dispose() множество раз, и при этом не приводить к ошибке. А дело в том, что StreamWriter во время Dispose() пытается вызвать Flush() на потоке. Но этот поток уже закрыл StreamReader, и вы получаете ошибку.

Как уже указали в другом ответе, вы можете использовать другой конструктор:

new StreamReader(bufferedStreamWhois, true, Encoding.UTF8, 1024, leaveOpen: true);

https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose

To help ensure that resources are always cleaned up appropriately, a Dispose method should be callable multiple times without throwing an exception.

Answer 2

Поток закрывает reader/writer. Можно оставить его открытым после выхода из using, для этого в конструкторе установить leaveOpen в true https://docs.microsoft.com/ru-ru/dotnet/api/system.io.streamreader.-ctor?view=netframework-4.7.2#System_IO_StreamReader__ctor_System_IO_Stream_System_Text_Encoding_System_Boolean_System_Int32_System_Boolean_

Answer 3

Вы действительно хотели создать читатель и писатель с одним и тем же потоком bufferedStreamWhois?

Исключение о закрытом потоке относится к bufferedStreamWhois. Читатель в своем Dispose закрывает bufferedStreamWhois, а потом то же самое делает писатель.

https://docs.microsoft.com/en-us/dotnet/api/system.io.streamwriter.-ctor?view=netframework-4.7.2#System_IO_StreamWriter__ctor_System_IO_Stream_

https://docs.microsoft.com/en-us/dotnet/api/system.io.streamreader.-ctor?view=netframework-4.7.2#System_IO_StreamReader__ctor_System_IO_Stream_

READ ALSO
StackOverflowException при включении Toggle

StackOverflowException при включении Toggle

Всем привет! Короче мне надо создать Toggle Group, но свой, потому что в Toggle Group Unity есть недостатки

143
C# работа с указателями как с цифрами

C# работа с указателями как с цифрами

Есть так называемый XOR списокДля его реализации надо сделать XOR указателей

168
Обращение к объектам других форм Xamarin

Обращение к объектам других форм Xamarin

В проекте на Xamarin есть MainPagexaml внутри которой лежит Grid

124
Не могу нарисовать линию в Visual Studio (в форме)

Не могу нарисовать линию в Visual Studio (в форме)

На форме я создал pictureBox и на нем хочу нарисовать линиями своё ФИОРазмеры pictureBox 776; 426 (залит черным цветом)

236