0

I have a network equipment to which I connect once using sockets, and the connection is maintained open all the time until application closes.

Now I have a class in C# that encapsulates the communication. There is a method SendMessage to the equipment. I need to use Socket.ReceiveAsync to get the response.

Let's say there are 3 methods: 1. GetEqValA(), GetEqValB(), GetEqValC() that call SendMessage with a specific message for the equipment.

I have created only one instance of socket Event args like that:

        _completeArgs = new SocketAsyncEventArgs();
        _completeArgs.SetBuffer(buffer, 0, buffer.Length);
        _completeArgs.UserToken = _mySocket;
        _completeArgs.RemoteEndPoint = _mySocket.RemoteEndPoint;
        _completeArgs.Completed += new EventHandler<SocketAsyncEventArgs>(DataAvailable);
        _mySocket.ReceiveAsync(_completeArgs);

Now, the DataAvailable method has something similar to the code below:

            for (int i = 0; i < e.BytesTransferred; i++)
            {
                _tcpData.Add(e.Buffer[i]);
            }

            if (_tcpData.Count == _expectedTcpDataCount)
            {
                _expectedTcpDataCount = -1;

                ProcessData();
                // I don't want to put here, because it will wait for data until
                // someone sends a message and the equipment responds with data
                //_mySocket.ReceiveAsync(e);
            }
            else
            {
                _mySocket.ReceiveAsync(e);
            }

Now, the 3 methods from above can be called by anyone, even different threads. I do have a lock mechanism for that.

My problem is that if I reuse _completeArgs in SendMessage for the next message to send, I get an exception that this eventArgs object is already in use by an asynchronous operation, whereas if I do the same(but not directly, by taking the SocketAsyncEventArgs e parameter from DataAvailable) in DataAvailable, no problem occurs.

                _mySocket.ReceiveAsync(_completeArgs);
                _mySocket.Send(pMessage);

The idea is that I don't want to call ReceiveAsync all the time, even if I know that nothing will come in there, but I want to call ReceiveAsync before sending any message to the device, because I know that I will get something.

The exception appears at method GetEqValC(), if I call them one after another in the sequence A,B,C.

What I don't understand, can you help me? Can I don what I want to do? I use .NET 3.5.

P.S. Summary: I need to keep the connection alive, but read something from it only when I know for sure I must have something in there. Only one call at a time will be. One send, followed by one receive!

XMight
  • 1,991
  • 2
  • 20
  • 36
  • Normally, you always have a read request outstanding and process data as it arrives. You can use a second independent socketargs instance for sending data.; I don't understand one if your comments. ReceiveAsync never blocks. – usr Aug 26 '14 at 15:06
  • I mean if I put it there, then it creates a new waiting operation, but for the moment I have nothing to wait for, I'm sure about that. I want to fire _mySocket.ReceiveAsync(_completeArgs) only if I know for sure that I will have some data to read. And I'm not sending there any socket args, I just call this before sending my data, to make sure someone will get it. – XMight Aug 26 '14 at 15:36
  • If you don't see any incoming data and you don't fire the read. How will you later know that data arrives? You need to have one read outstanding so that you can notice incoming data. Why don't you want to fire the read if there is no data to read? – usr Aug 26 '14 at 15:38
  • Because before sending something I call ReceiveAsync to wait for data. The thing is that I use now a worker thread to maintain this reading all the time, and that's why I want to get rid of this call inside DataAvailable, so to get rid of the thread, because receiveAsync anyway uses a thread from threadPool, and fire it only when I need. – XMight Aug 26 '14 at 15:50
  • ReceiveAsync does not block any thread, not even a thread-pool thread. I don't really get what you are trying to accomplish here. I don't think all the relevant code is here to find any problem. – usr Aug 26 '14 at 15:55

0 Answers0