Исключение System.IO.IOException при попытке завершить поток - PullRequest
6 голосов
/ 06 января 2012

Я изучаю сетевой код и многопоточность в Monodevelop, используя C # с GTK #.Я никогда раньше этого не делал, и теперь я чувствую, что мне нужно сделать оба сразу.

Я использовал учебную программу чата, которая не обрабатывает ошибки, и я обнаружил ошибку, которая происходит вклиент каждый раз, когда я отключаюсь от сервера.Код, который находится в потоке, прослушивающем сообщения, выглядит следующим образом в окружении операторов try / catch:

            try
        {
            while (Connected)
            {
                if (!srReceiver.EndOfStream && Connected)
                {
                    string temp = srReceiver.ReadLine();
                    // Show the messages in the log TextBox
                    Gtk.Application.Invoke(delegate
                    {
                        UpdateLog(temp);
                    });
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());   
        }

После чего функция завершается, а поток заканчивается.

Код, который заканчиваетсясоединение выглядит следующим образом и выполняется в основном потоке:

        private void CloseConnection(string Reason)
    {
        // Show the reason why the connection is ending
        UpdateLog(Reason);
        // Enable and disable the appropriate controls on the form
        txtIp.Sensitive = true;
        txtUser.Sensitive = true;
        txtMessage.Sensitive = false;
        btnSend.Sensitive = false;
        btnConnect.Label = "Connect";

        // Close the objects
        Connected = false;
        swSender.Close();
        srReceiver.Close();
        tcpServer.Close();
    }

И приведенные выше инструкции try / catch перехватывают эту ошибку:

System.IO.IOException: Невозможно выполнитьчтение данных из транспортного соединения: операция блокировки была прервана вызовом WSACancelBlockingCall.---> System.Net.Sockets.SocketException: операция блокировки была прервана вызовом WSACancelBlockingCall

в System.Net.Sockets.Socket.Receive (байт [], смещение Int32, размер Int32,SocketFlags socketFlags)

в System.Net.Sockets.NetworkStream.Read (буфер Byte [], смещение Int32, размер Int32)

--- Конец трассировки стека внутренних исключений ---

в System.Net.Sockets.NetworkStream.Read (буфер в байтах [], смещение Int32, размер Int32)

в System.IO.StreamReader.ReadBuffer ()

вSystem.IO.StreamReader.get_EndOfStream ()

в ChatClientGTK.MainWindow.ReceiveMessages () в g: \ Android \ Tutes \ ChatClientRemake \ ChatClientGTK \ MainWindow.cs: строка 157

Теперь, насколько я могу судить, когда srReciever.Close () происходит в главном потоке, srReciever.ReadLine () все еще пытается выполнить в потоке прослушивания, где и заключается проблема, но даже когда я закомментирую srReciever.Close (), я все еще получаю ошибку.

AsНасколько я могу судить, нет никаких побочных эффектов, вызванных просто обнаружением ошибки и продолжением, но это не совсем подходит мне.Нужно ли исправлять эту ошибку, и если да, у кого-нибудь есть идеи?

Ответы [ 2 ]

2 голосов
/ 06 января 2012

Ошибка в порядке. Если вы действительно хотите, чтобы это исчезло, вы можете включить в свой протокол команду «пока». Таким образом, если сервер решает отключиться, перед самым отключением он отправляет «пока» клиенту, поэтому клиент тоже отключается, и большая вероятность того, что исключение не будет выброшено. Но вы все равно должны быть готовы поймать его, если его когда-нибудь выбросят. А потом проигнорируй это.

2 голосов
/ 06 января 2012

Вместо использования ReadLine, вы не можете просто выполнить чтение и создать строку до тех пор, пока не будет обнаружен CrLf, а затем вывести ее для обновления журнала.

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

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

Также я, вероятно, поймал бы конкретное исключение

catch (IOException ex)
        {
            Console.WriteLine(ex.ToString());
        }
catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...