Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does using the Asynchronous Programming Model in .Net not lead to StackOverflow exceptions?

For example, we call BeginReceive and have the callback method that BeginReceive executes when it has completed. If that callback method once again calls BeginReceive in my mind it would be very similar to recursion. How is that this does not cause a stackoverflow exception. Example code from MSDN:

private static void Receive(Socket client) {
    try {
        // Create the state object.
        StateObject state = new StateObject();
        state.workSocket = client;

        // Begin receiving the data from the remote device.
        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 {
        // Retrieve the state object and the client socket 
        // from the asynchronous state object.
        StateObject state = (StateObject) ar.AsyncState;
        Socket client = state.workSocket;

        // Read data from the remote device.
        int bytesRead = client.EndReceive(ar);

        if (bytesRead > 0) {
            // There might be more data, so store the data received so far.
        state.sb.Append(Encoding.ASCII.GetString(state.buffer,0,bytesRead));

            // Get the rest of the data.
            client.BeginReceive(state.buffer,0,StateObject.BufferSize,0,
                new AsyncCallback(ReceiveCallback), state);
        } else {
            // All the data has arrived; put it in response.
            if (state.sb.Length > 1) {
                response = state.sb.ToString();
            }
            // Signal that all bytes have been received.
            receiveDone.Set();
        }
    } catch (Exception e) {
        Console.WriteLine(e.ToString());
    }
}
like image 400
uriDium Avatar asked Jan 14 '11 14:01

uriDium


1 Answers

BeginReceive registers a callback function associated with an overlapped IO operation. The callback will be called by the operating system when the data is available, but the BeginReceive call returns immediately, and therefore your invocation of ReceiveCallback also finishes.
Think of the actual IO as happening in a thread that doesn't belong to you, but rather to the OS. Your act of registering the callback just says "keep calling me when something happens", but it doesn't get added to the stack. That's why it is called asynchronous.

like image 184
MK. Avatar answered Oct 06 '22 07:10

MK.