Thursday, April 15, 2010

Solve Exception Message: The IAsyncResult object was not returned from the corresponding asynchronous method on this class

Recently I was got a weird error on my Windows CE code (.NET compact framework) which was asynchronously listening for UDP (or may be same for TCP) messages.

Exception Message

Error Message: The IAsyncResult object was not returned from the corresponding asynchronous method on this class.
CallStack for debug purpose:
    at System.Net.Sockets.Socket.EndReceiveFrom()
    at BallyTech.SocketListener.UdpSocketListener.OnReceive()
    at System.Net.LazyAsyncResult.InvokeCallback()
    at WorkerThread.doWork()
    at WorkerThread.doWorkI()
    at WorkItem.doWork()
    at System.Threading.Timer.ring()

Issue

When frequently Open/Close UDP sockets, above exception comes while closing one socket and start listening on another socket on the same port. OnReceive method is called (only once) for the previous (closed) socket while doing “Start Listening” on new socket on the same port. As old socket is already dereferenced and closed, you will get above socket exception on EndReceiveFrom or EndReceive method.

Solution

In short, you have to ignore the calls of your OnReceive (or similar) for Old socket which you no longer use i.e. closed sockets.

Note that when you call BeginReceiveFrom to start listening for messages, it returns an instance of IAsyncResult. Don’t ignore this and store it into class level private variable (let’s say variable name currentAsyncResult).

Now make modification into  your OnReceive method to ignore any message which is not for currentAsyncResult.

private void OnReceive(IAsyncResult ar)
{
try
{
if (ar == currentAynchResult)
{
IPEndPoint ipeSender = new IPEndPoint(IPAddress.Any, 0);
EndPoint epSender = (EndPoint)ipeSender;

//Error comes here if we didn't have (ar == currentAynchResult) check
int bytesRead = udpSocket.EndReceiveFrom(ar, ref epSender);
//process further
}
else
{
//Ignore
}
BeginReceive();
}
catch (Exception ex)
{
//Log exception. Don't throw exception. Most probably BeginReceive failed.
}
}

Notice the if (ar == currentAynchResult) check where we got currentAynchResult from BeginReceiveFrom method while starting listening from new socket.

Happy Networking!