Как я могу использовать «использование» в C #, не получая «InvalidOperationException»? - PullRequest
1 голос
/ 25 февраля 2009

Я пытаюсь заменить следующий код, который работает нормально

TcpClient oC = new TcpClient(ip, port);
oC = new TcpClient(ip, port);
StreamReader messageReader;

try {
   messageReader = new StreamReader(oC.GetStream(), Encoding.ASCII);
   reply = messageReader.ReadLine();
}

с

try {
   using (messageReader = new StreamReader(oC.GetStream(), Encoding.ASCII))
   {
       reply = messageReader.ReadLine();
   }
}

Но я получаю InvalidOperationException высказывание

Операция не разрешена неподключенные розетки.

В чем проблема и как ее исправить?

Подробнее: У меня есть oc.Connect перед этим кодом, поэтому я подключаюсь, и когда он хочет использоваться впервые, он работает нормально, только после этого я получаю это исключение Я немного поиграл с этим и теперь получаю:

Невозможно получить доступ к удаленному объект. \ r \ nИмя объекта: 'System.Net.Sockets.Socket'.

Ответы [ 6 ]

12 голосов
/ 25 февраля 2009

Попробуйте вызвать oc.Connect перед созданием StreamReader. Пока сокет не подключен, читать нечего и, следовательно, исключение.

4 голосов
/ 25 февраля 2009

Просто повторяю мой комментарий к ответу Джареда.

Али прокомментировал:

У меня есть oc.Connect до этого, и это отлично работает в первый раз, но 2-й раз это случается, я тоже получаю "Невозможно получить доступ к удаленному объект. \ r \ nИмя объекта: 'System.Net.Sockets.Socket'. "- Али (13 минут назад)

Я прокомментировал:

"и это потому, что StreamReader принимает владение потоком и закрывается и располагает потоком, который вы инициируете это с. В этом случае Сетевой поток TcpClient. Theres нет необходимости утилизировать StreamReader здесь "

2 голосов
/ 13 августа 2014

Так что используйте правильный конструктор .

using (messageReader = 
        new StreamReader(oC.GetStream(), Encoding.ASCII, false, 4096, true))
{
   reply = messageReader.ReadLine();
}

Обратите внимание на последний параметр leaveOpen: и прочитайте, что он означает в документах .

Тем не менее, IIRC, StreamReader буферизует содержимое из потока (по умолчанию 4096 байт-считываний), поэтому, когда вы располагаете StreamReader, вы можете быть удивлены, обнаружив, что позиция потока вышла за пределы данные, которые вы читаете с помощью StreamReader. Предоставление StreamReader права собственности всегда является хорошей идеей. Разве вы не можете оставить его открытым, пока не прочитаете все данные?

1 голос
/ 25 февраля 2009

Кроме того, вы объявили messageReader как StreamWriter. Разве это не должен быть StreamReader?

StreamWriter messageReader;

[Исправлено OP]

Еще один совет, лучше создать экземпляр объекта в операторе using, а не передавать его внутрь. Это может быть не фактическая причина вашего исключения, а из MSDN :

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

1 голос
/ 25 февраля 2009

Слушайте Джареда, и ваше настоящее исключение, использование не имеет к этому никакого отношения, ваша попытка может замаскировать ошибку и скрыть реальную проблему. Настоящая ошибка в том, что вы никогда не подключали сокет, прежде чем пытаться читать.

Edit:

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

Есть ли у вас более полный пример, который вы могли бы опубликовать, который показал бы объем вашего соединения в сравнении с использованием, чтобы мы могли точно видеть, где базовый сокет выбирается GC?

0 голосов
/ 25 февраля 2009

Я думаю, что вы не можете сначала определить StreamWriter, а затем использовать его с использованием.

Попробуйте это:

TcpClient oC = new TcpClient(ip, port);
oC = new TcpClient(ip, port);

try {
   using (StreamWriter messageReader = new StreamReader(oC.GetStream(), Encoding.ASCII))
   {
       reply = messageReader.ReadLine();
   }
}
...