2012-01-06 29 views
6

Estoy aprendiendo netcode y multihilo en Monodesarrollo, usando C# con GTK #. Nunca lo había hecho antes, y ahora me veo en la necesidad de hacer ambas cosas a la vez.Excepción de System.IO.IOException al intentar finalizar el hilo

He utilizado un programa de chat tutorial que no tiene ningún error de manejo, y he detectado un error que ocurre en el cliente cada vez que me desconecto del servidor. El código que se encuentra en un subproceso de escucha para los mensajes es el siguiente, rodeado de declaraciones 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()); 
     } 

Después de lo cual termina la función y el hilo termina.

El código que finaliza la conexión se parece a esto, y se ejecuta en el hilo principal:

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

Y el try/catch declaraciones anteriores captura este 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

Ahora, en lo como puedo decir, cuando srReciever.Close() sucede en el hilo principal, srReciever.ReadLine() todavía está intentando ejecutar en el hilo de escucha, que es donde reside el problema, pero incluso cuando hago un comentario de srRecverver.Close() , Aún tengo el error.

Por lo que puedo decir, no hay efectos secundarios causados ​​por simplemente atrapar el error y seguir adelante, pero eso realmente no me sienta bien. ¿Debo corregir este error? De ser así, ¿alguien tiene alguna idea?

+1

Simplemente otro ejemplo de excepción lanzada para indicar una condición no excepcional. La mayoría de las personas considera que el diseño de la API es malo, pero con .NET BCL es un lugar común. –

Respuesta

2

En lugar de utilizar una ReadLine, ¿no puede simplemente leer y construir la cadena hasta que se detecte un CrLf y luego generarlo para actualizar el registro.

ReadLine es una llamada de bloqueo, lo que significa que se quedará allí y siempre se producirá un error si la conexión se cierra.

De lo contrario, podría ignorar el error. Sé a qué te refieres cuando dices que no le sienta bien, pero a menos que alguien más me pueda aclarar, no veo que haya ninguna fuga en los recursos debido a eso y si se trata de un error esperado, entonces puedes manejarlo adecuadamente. .

también que probablemente detectar la excepción específica

catch (IOException ex) 
     { 
      Console.WriteLine(ex.ToString()); 
     } 
catch (Exception ex) 
     { 
      Console.WriteLine(ex.ToString()); 
     } 
+0

Solo quiero agregar que aún necesita manejar ese error, independientemente del método que utilice, ya que tendrá que dar cuenta del abandono de la conexión de red. –

+0

Impresionante, eso es lo que sospechaba. Atraparé esa excepción en particular y seguiré con mi vida. ¡Gracias! – Excrubulent

2

El error está muy bien. Si realmente quieres que desaparezca, puedes incluir un comando "bye" en tu protocolo. Por lo tanto, si el servidor decide desconectarse, justo antes de desconectarse, envía un "adiós" al cliente, por lo que el cliente también se desconecta, y es muy probable que la excepción no se produzca. Pero aún debes estar preparado para atraparlo si alguna vez se lanza. Y luego ignóralo.

+0

No he dedicado mucho tiempo al código del servidor; aún tengo que evitar que se bloquee cada vez que un cliente se desconecta inesperadamente. Me imagino que es el mismo tipo de cosas, donde se arroja una excepción para una situación bastante común. Además, la excepción en el cliente se produce no cuando el servidor se desconecta, sino cuando el cliente decide desconectarse. Voy a reescribir ambos programas antes de intentar hacer algo con ellos, prefiero haber escrito todas las líneas, así que estoy familiarizado con lo que está haciendo exactamente el código. – Excrubulent

Cuestiones relacionadas