Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

System.IO.IOException exception when attempting to end thread

I'm learning netcode and multithreading in Monodevelop, using C# with GTK#. I've never done either before, and now I find myself needing to do both at once.

I've used a tutorial chat program that has no error handling, and I've caught an error that happens in the client every single time I disconnect from the server. The code that sits in a thread listening for messages is as follows, surrounded by try/catch statements:

            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());   
        }

After which the function finishes and the thread ends.

The code that ends the connection looks like this, and runs on the main thread:

        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();
    }

And the try/catch statements above catch this error:

System.IO.IOException: Unable to read data from the transport connection: A blocking operation was interrupted by a call to WSACancelBlockingCall. ---> System.Net.Sockets.SocketException: A blocking operation was interrupted by a call to WSACancelBlockingCall

at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)

at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)

--- End of inner exception stack trace ---

at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)

at System.IO.StreamReader.ReadBuffer()

at System.IO.StreamReader.get_EndOfStream()

at ChatClientGTK.MainWindow.ReceiveMessages() in g:\Android\Tutes\ChatClientRemake\ChatClientGTK\MainWindow.cs:line 157

Now, as far as I can tell, when srReciever.Close() happens in the main thread, srReciever.ReadLine() is still trying to execute in the listening thread, which is where the problem lies, but even when I comment out srReciever.Close(), I still get the error.

As far as I can tell, there are no side-effects caused by just catching the error and moving on, but that doesn't really sit right with me. Do I need to fix this error, and if so, does anyone have any ideas?

like image 735
Excrubulent Avatar asked Jan 06 '12 03:01

Excrubulent


2 Answers

Instead of using a ReadLine, can't you just do a Read and build up the String until a CrLf is detected then output that to update log.

ReadLine is a blocking call meaning it will sit there and always error if the connection is closed.

Otherwise you could just ignore the error. I know what you mean when you say it doesn't sit right but unless anyone else can enlighten me, I don't see that there is any leak in resources due to it and if it is an expected error then you can handle it appropriately.

Also I would probably catch the specific exception

catch (IOException ex)
        {
            Console.WriteLine(ex.ToString());
        }
catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
like image 176
Adam Avatar answered Oct 23 '22 15:10

Adam


The error is fine. If you really want it to go away, you can include a "bye" command in your protocol. So, if the server decides to disconnect, right before disconnecting he sends a "bye" to the client, so the client disconnects too, and most chances are that the exception will not be thrown. But you should still be prepared to catch it if it ever gets thrown. And then ignore it.

like image 22
Mike Nakis Avatar answered Oct 23 '22 14:10

Mike Nakis