调用EndReceive时抛出ObjectDisposedException(异步客户端套接字)

时间:2018-01-30 10:26:47

标签: c# multithreading sockets asynchronous

我正在使用C#程序,我想与wifi模块(RN 171)交谈。

在我的Program.cs中,当我收到RabbitMQ消息时,我直接调用 Start 方法。

我从this示例(异步客户端套接字示例)开始。

指示错误发生在以下行:

  

int bytesRead = client.EndReceive(ar);

但它现在真的出现了:

  

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

此解决方案有效(wifi模块对我的命令做出反应,但异常并不让我满意)。这是我的代码,感谢您的帮助:

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

}

感谢您提供任何帮助/解释:)

1 个答案:

答案 0 :(得分:1)

如果您阅读documentation,则表明ObjectDisposedExceptionEndReceive()方法的预期结果,如果套接字在接收处于挂起状态时关闭。这是套接字通知您的应用程序的方式BeginReceive()操作结束的原因是套接字已关闭。

try..catch例外情况外,没有其他事情可做,并且可能需要进行任何清理。

<强>更新

我还注意到你对线程的处理有点不寻常。使用此应用程序,您使用的是异步方法(BeginConnect()BeginReceive()),但您手动阻止主线程,直到每个方法都使用ManualResetEvents完成。

从代码的外观来看,您似乎想要连接并阻塞,直到您从服务器读取响应,因此我建议将异步方法更改为同步方法(Connect(),{{1} })并在Receive()方法中执行所有操作。这不仅可以消除在一个线程上关闭套接字而另一个线程正在读取它时遇到的问题,但会使代码更加简洁。