2012-01-06 15 views
6

Sto imparando netcode e multithreading in Monodevelop, utilizzando C# con GTK #. Non l'ho mai fatto prima, e ora mi trovo a doverli fare entrambi contemporaneamente.Eccezione System.IO.IOException durante il tentativo di terminare il thread

Ho utilizzato un programma di chat tutorial che non ha errori di gestione e ho rilevato un errore che si verifica nel client ogni volta che si disconnette dal server. Il codice che si trova in un thread di ascolto per i messaggi è il seguente, circondato da dichiarazioni 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()); 
     } 

Dopo che le finiture di funzione e le estremità del filo.

Il codice che termina il collegamento si presenta così, e viene eseguito sul thread principale:

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

E il try/catch dichiarazioni di cui sopra cattura questo errore:

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

Ora, per quanto come posso dire, quando srReciever.Close() accade nel thread principale, srReciever.ReadLine() sta ancora provando ad eseguire nel thread di ascolto, che è dove si trova il problema, ma anche quando commento a srReciever.Close() , Ho ancora l'errore.

Per quello che posso dire, non ci sono effetti collaterali causati dal semplice rilevamento dell'errore e dall'andare avanti, ma questo non mi sta proprio bene. Devo correggere questo errore e, in caso affermativo, qualcuno ha qualche idea?

+1

Solo un altro esempio di un'eccezione generata per indicare una condizione non eccezionale. La maggior parte delle persone considera che una cattiva progettazione dell'API, ma con .NET BCL è normale. –

risposta

2

Invece di utilizzare un ReadLine, non è sufficiente eseguire una lettura e creare la stringa fino a quando non viene rilevato un CrLf, quindi inviarlo per aggiornare il registro.

ReadLine è una chiamata di blocco che significa che si siederà lì e sempre errore se la connessione è chiusa.

Altrimenti si potrebbe semplicemente ignorare l'errore. So cosa intendi quando dici che non è giusto, ma a meno che nessun altro possa illuminarmi, non vedo che ci sono perdite di risorse a causa di esso e se si tratta di un errore previsto, puoi gestirlo in modo appropriato .

Inoltre mi sarebbe probabilmente intercettare l'eccezione specifica

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

Voglio solo aggiungere che è ancora necessario gestire tale errore indipendentemente dal metodo scelto, poiché è necessario considerare l'interruzione della connessione di rete. –

+0

Fantastico, questo è quello che sospettavo. Prenderò questa particolare eccezione e andrò avanti con la mia vita. Grazie! – Excrubulent

2

L'errore è bene. Se vuoi davvero che vada via, puoi includere un comando "ciao" nel tuo protocollo. Quindi, se il server decide di disconnettersi, prima di disconnettersi invia un "ciao" al client, quindi anche il client si disconnette, e la maggior parte delle probabilità è che l'eccezione non venga lanciata. Ma dovresti comunque essere pronto a prenderlo se mai viene lanciato. E poi ignoralo.

+0

Non ho speso molto tempo sul codice server - Devo ancora impedirgli di andare in crash ogni volta che un client si disconnette inaspettatamente. Immagino sia lo stesso tipo di cosa, in cui un'eccezione viene lanciata per una situazione abbastanza ordinaria. Inoltre, l'eccezione nel client non viene generata quando il server si disconnette, ma quando il client decide di disconnettersi. Ho intenzione di riscrivere entrambi i programmi prima ancora che provassi a fare qualcosa con loro, però - preferisco aver scritto ogni riga, quindi ho familiarità con esattamente ciò che il codice sta facendo. – Excrubulent

Problemi correlati