0

I've received an assignment in my C# course to build a multi-client chat in WinForms using the TcpClient / TcpServer classes with the use of Serialization & Deserialization via BinaryFormatter.

When I'm using the Disconnect method from the client side I instantly get this error on the line incomingData = binFormat.Deserialize(stream);.

ObjectDisposedException - Cannot access a disposed object

Client side 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;
        }


    }
}
Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
Gal Ratzkin
  • 124
  • 2
  • 8
  • Your worker thread will be blocked on the Deserialize() call, waiting for the stream to deliver more data. When you call Disconnect then the stream read completes immediately and the Deserialize call falls over on an ObjectDisposedException. Simplest way to deal with it is to add another catch clause: catch (ObjectDisposedException) { return; } – Hans Passant Jun 18 '16 at 18:01

1 Answers1

0

You should JOIN() the thread instead saying below, cause by the time your thread is trying to access binFormat instance, your main thread has already comleted and so that instance field has been disposed of. Thus you are receiving the said exception.

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

You can as well consider changing your method signature to receive one BinaryFormatter instance like below

    public void Recieve(object Info, BinaryFormatter formatter)
    {

(OR) You create a instance of same inside your method block and use the same like

    public void Recieve(object Info)
    {
       BinaryFormatter format = new BinaryFormatter();
       incomingData = format.Deserialize(stream); 
Rahul
  • 76,197
  • 13
  • 71
  • 125