0

Ich habe einen Auftrag in meinem C# Kurs erhält ein Multi-Client-Chat in WinForms zu bauen.ObjectDisposedException in einer Client-Server-Anwendung

Wenn ich die Disconnect Methode von der Clientseite verwende, bekomme ich sofort diesen Fehler in der Zeile incomingData = binFormat.Deserialize(stream);.

ObjectDisposedException - Cannot access a disposed object 

Client-Seite Code:

using System; 
using System.Net; 
using System.Net.Sockets; 
using System.Runtime.Serialization.Formatters.Binary; 
using System.Threading; 
using CommonResources; 
using System.Windows.Forms; 
using System.IO; 

namespace shekerclient 
{ 
    [Serializable] 

    public class ClientConnection 
    { 
     GuestInfo ClientInformation; 
     GuestMenager ClientStats; 
     Thread clientListenThread; 
     public IPEndPoint ServeripAdress; 
     public TcpClient tcpUser; 
     private IncomingMessageManager Menage; 
     private bool IsConnected; 
     BinaryFormatter binFormat = new BinaryFormatter(); 
     public int onlineUsers; 
     NetworkStream stream; 

     public bool ConnectionStatus 
     { 

      get { return IsConnected; } 

     } 

     public ClientConnection(string ip, int port, IncomingMessageManager Mngr, 
       GuestInfo clientInformation, GuestMenager ClientStats) 
     { 

      ServeripAdress = new IPEndPoint(IPAddress.Parse(ip), port); 
      this.ClientStats = ClientStats; 
      this.ClientInformation = clientInformation; 
      Menage = Mngr; 
      Connect(); 

      if (tcpUser.Client.Connected) 
      { 
       var stream = tcpUser.GetStream(); 
       clientListenThread = new Thread(new ParameterizedThreadStart(Recieve)); 
       clientListenThread.IsBackground = true; 
       clientListenThread.Start(null); 
       Thread.Sleep(2000); 
       binFormat.Serialize(stream, ClientInformation); 
      } 

     } 
     public void Connect() 
     { 
      try 
      { 
       tcpUser = new TcpClient(); 
       tcpUser.Connect(ServeripAdress); 
       IsConnected = true; 
      } 
      catch (Exception Error) 
      { 
       MessageBox.Show(Error.Message); 
      } 
     } 

     public void Send(object Msg) 
     { 
      Msg = (ChatMessage)Msg; 

      var SendStream = tcpUser.GetStream(); 

      binFormat.Serialize(SendStream, Msg); 
     } 

     public void Recieve(object Info) 
     { 
      this.stream = tcpUser.GetStream(); 

      while (true) 
      { 
       if (IsConnected) 
       { 
        { 
         object incomingData = null; 

         try 
         { 
          incomingData = binFormat.Deserialize(stream); 
         } 
         catch (IOException Error) 
         { 
          MessageBox.Show(Error.Message); 
         } 


         if (incomingData != null && incomingData.GetType()==typeof(GuestInfo)) 

         { 
          var ClientInfo = incomingData as GuestInfo; 
          ClientStats.AddGuest(ClientInfo); 
         } 
         else if (incomingData != null && incomingData.GetType()==typeof(ChatMessage)) 
         { 

          var Msg = incomingData as ChatMessage; 
          Menage.AddMessage(Msg); 

         } 

        } 
       } 
      } 


     } 


     public void Disconnect() 
     { 

      IsConnected = false; 
      tcpUser.GetStream().Flush(); 
      tcpUser.Client.Disconnect(false); 
      tcpUser.Close(); 
      tcpUser = null; 
     } 


    } 
} 
+0

Ihr Worker-Thread wird beim Deserialize() - Aufruf blockiert und wartet darauf, dass der Stream mehr Daten liefert. Wenn Sie Disconnect aufrufen, wird der Stream-Lesevorgang sofort abgeschlossen und der Deserialize-Aufruf fällt bei einer ObjectDisposedException ab. Der einfachste Weg, um damit umzugehen, besteht darin, eine weitere catch-Klausel hinzuzufügen: catch (ObjectDisposedException) {return; } –

+0

Danke !!!!! –

Antwort

0

Sie den Faden JOIN() sollten stattdessen sagen unten, weil durch die Zeit Thread binFormat Beispiel Ihr Hauptthread bereits comleted zuzugreifen versucht, und so Dieses Instanzfeld wurde entsorgt. So erhalten Sie die genannte Ausnahme.

clientListenThread.Start(); 
clientListenThread.Join(); 

Sie können prüfen, wie gut Ihre Methode Signatur zu ändern, wie eine BinaryFormatter Instanz erhalten unter

public void Recieve(object Info, BinaryFormatter formatter) 
    { 

(OR) Sie in Ihrer Methode Block eine Instanz dieselbe erstellen und verwenden die gleichen wie

public void Recieve(object Info) 
    { 
     BinaryFormatter format = new BinaryFormatter(); 
     incomingData = format.Deserialize(stream); 
Verwandte Themen