I've inherited a socket callback routine I'm trying to debug. It does asynchronous TCP communication with an EndReceive() immediately followed by a BeginReceve() so it's always listening. It's filled with "when hit" breakpoints that display a message and continue for diagnostics.
Because it's an asynchronous callback it may be called by the system multiple times for one BeginReceive() even if it's in the middle of processing a previous callback. Usually this is in a new thread, which is why I have a lock (a critical section) for the whole thing. But sometimes it seems to get reentered by the same thread even before it's exited. How is this possible? What am I doing wrong?
He's my trace (using 'When Hit' breakpoints) . . .
Socket_DataArrival() – Entering … managedThreadID=11 Socket_DataArrival() - first statement in lock . . . managedThreadID=11 Socket_DataArrival() - EndReceive() ... managedThreadID=11 Socket_DataArrival() - BeginReceive() . . . managedThreadID=11 Socket_DataArrival() – Entering … managedThreadID=11 Socket_DataArrival() - first statement in lock . . . managedThreadID=11 Socket_DataArrival() - EndReceive() ... managedThreadID=11 Socket_DataArrival() - BeginReceive() . . . managedThreadID=11 Socket_DataArrival() - exiting at end of routine . . . managedThreadID=11 Socket_DataArrival() - exiting at end of routine . . . managedThreadID=11
and here's the routine (proprietary code commented out) . . .
private void Socket_DataArrival(IAsyncResult ar)
{
StateObject stateObject;
int bytesReceived;
int managedThreadId = Thread.CurrentThread.ManagedThreadId;
lock (inputLock)
{ // "Entering..."
try
{
_Receiving = false; //"first statement in lock"
stateObject = (StateObject)ar.AsyncState;
bytesReceived = stateObject.sSocket.EndReceive(ar);
_Receiving = true;
_StateObject = new StateObject(2048, _TCPConn); //2048 = arbitrary number
_StateObject.tag = "Socket_DataArrival ";
_TCPConn.BeginReceive(
_StateObject.sBuffer,
0,
_StateObject.sBuffer.Length,
SocketFlags.None,
new AsyncCallback(Socket_DataArrival),
_StateObject);
}
catch (Exception exc)
{
subs.LogException("Socket_DataArrival", exc);
}
// proprietary stuff goes here
} // end critical section
return;
}
inputLock is defined at the class level as . . .
private Object inputLock = new Object();
How can the same thread enter it a second time before it's exited the first time?