James Farmer
James Farmer

Reputation: 23

C# TCP Async EndReceive() throws InvalidOperationException ONLY on Windows XP 32-bit

I have a simple C# Async Client using a .NET socket that waits for timed messages from a local Java server used for automating commands. The messages come in asynchronously and is written to a ring buffer. This implementation seems to work fine on Windows Vista/7/8 and OSX, but will randomly throw this exception while it's receiving a message from the local Java server:

Unhandled Exception: System.InvalidOperationException: EndReceive can only be called once for each asynchronous operation.
    at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult, SocketError& errorCode)
    at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
    at SocketTest.Controller.RecvAsyncCallback(IAsyncResult ar)
    at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
    ...

I've looked online for this error, but have found nothing really helpful. This is the code where it seems to break:

/// <summary>
/// Callback to receive socket data
/// </summary>
/// <param name="ar">AsyncResult to pass to End</param>
private void RecvAsyncCallback(IAsyncResult ar)
{
    // The exception will randomly happen on this call
    int bytes = _socket.EndReceive(_recvAsyncResult);

    // check for connection closed
    if (bytes == 0)
    {
        return;
    }

    _ringBuffer.Write(_buffer, 0, bytes);

    // Checks buffer
    CheckBuffer();

    _recvAsyncResult = _sock.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, RecvAsyncCallback, null);
}

The error doesn't happen on any particular moment except in the middle of receiving a message. The message itself can be any length for this to happen, and the exception can happen right away, or sometimes even up to a minute of perfect communication.

I'm pretty new with sockets and network communication, and I feel I might be missing something here. I've tested on at least 8 different computers, and the only similarity with the computers that throw this exception is that their OS is Windows XP 32-bit.

Upvotes: 2

Views: 2798

Answers (1)

Michael J. Gray
Michael J. Gray

Reputation: 9916

You will want to follow the convention shown here. You are passing in an IAsyncResult to Socket.BeginReceive that represents a different point in the context or an entirely different context.

Make sure that in your callback you are using the parameter that is passed in when you call EndReceive.

Windows XP may have a bug fix in it, depending on your service pack and what other things you have installed, that catches a context sharing scenario or perhaps it has a bug introduced which does not correctly manage the contexts. It's hard to tell if it's an environment issue or not, without extensive testing.

Upvotes: 1

Related Questions