Raphaël Dev
Raphaël Dev

Reputation: 63

ObjectDisposedException throw when EndReceive is call (Asynchronous Client Socket)

I'm working on a C# program where I want to talk with a wifi module (RN 171).

In my Program.cs, when I receive a RabbitMQ message, i call directly my Start method.

I started from this example (Asynchronous Client Socket Example).

The error is indicated to occur at line :

int bytesRead = client.EndReceive(ar);

But it really appears at this moment :

client.Shutdown(SocketShutdown.Both);
client.Close();

This solution works (wifi module react to my commands but the exception does not please me). Here's my code, thanks for any help :

using System.Text;
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace SDK_TestApp
{

public class Electricity
{
    private const int port = 2000;
    private static ManualResetEvent connectDone = new ManualResetEvent(false);
    private static ManualResetEvent sendDone = new ManualResetEvent(false);
    private static ManualResetEvent receiveDone = new ManualResetEvent(false);
    private static String response = String.Empty;

    public bool Start(String commande)
    {
        try
        {

            System.Net.IPAddress ipAddress = System.Net.IPAddress.Parse("192.168.1.17");

            IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

            Socket theClient = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            theClient.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), theClient);

            connectDone.WaitOne();

            Receive(theClient);
            receiveDone.WaitOne();

            Console.WriteLine("Connexion : {0}", response);

            Send(theClient, commande);
            sendDone.WaitOne();

            Receive(theClient);
            receiveDone.WaitOne();

            Console.WriteLine("Response received : {0}", response);

            theClient.Shutdown(SocketShutdown.Both);
            theClient.Close();

            return true;

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
            return false;
        }
    }

    private static void ConnectCallback(IAsyncResult ar)
    {
        try
        {
            Socket client = (Socket)ar.AsyncState;

            client.EndConnect(ar);

            connectDone.Set();

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

    private static void Receive(Socket client)
    {
        try
        {

            StateObject state = new StateObject();
            state.workSocket = client;

            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

    private static void ReceiveCallback(IAsyncResult ar)
    {
        try
        {

            StateObject state = (StateObject)ar.AsyncState;

            Socket clientReceiveCB = state.workSocket;

            SocketError test;

            int bytesRead = clientReceiveCB.EndReceive(ar, out test);

            Console.WriteLine("test endReceive : " + test);

            string testResponse = Encoding.ASCII.GetString(state.buffer, 0, bytesRead); 
            state.sb.Append(testResponse);

            clientReceiveCB.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);      

            if (state.sb.Length > 1)
            {
                response = state.sb.ToString();
            }

            receiveDone.Set();

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

    private static void Send(Socket client, String data)
    {

        byte[] byteData = Encoding.ASCII.GetBytes(data);
        client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), client);

    }

    private static void SendCallback(IAsyncResult ar)
    {
        try
        {
            Socket client = (Socket)ar.AsyncState;

            client.EndSend(ar);

            sendDone.Set();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

}

public class StateObject
{
    public Socket workSocket = null;
    public const int BufferSize = 256;
    public byte[] buffer = new byte[BufferSize];
    public StringBuilder sb = new StringBuilder();
}

}

Thanks for any help / explanation :)

Upvotes: 2

Views: 1428

Answers (1)

Trevor
Trevor

Reputation: 1271

If you read the documentation, it states that the ObjectDisposedException is an expected result of the EndReceive() method if the socket is closed while the receive is pending. It's the way the socket notifies your application that the reason the BeginReceive() operation ended was because the socket was closed.

Nothing to do really except for try..catch the exception, and perform any clean-up you might need to do.

Update

I also notice that your handling of the threads is a little unusual. With this app, you are using the asynchronous methods (BeginConnect(), BeginReceive()), but you are manually blocking the main thread until each of these complete with the ManualResetEvents.

From the look of the code it looks like you want to connect and block until you read the response from the server, so I would suggest changing the asynchronous methods to the synchronous ones (Connect(), Receive()) and do everything in the Start method. That would not only eliminate the issues you are having with closing the socket on one thread while another thread is reading it, but will make the code a lot more succinct.

Upvotes: 3

Related Questions