.net - 为什么在 .Net 中使用异步编程模型不会导致 StackOverflow 异常?

标签 .net asynchronous

例如,我们调用BeginReceive 并具有BeginReceive 在完成时执行的回调方法。如果该回调方法再次在我看来调用 BeginReceive,它将与递归非常相似。这怎么不会导致 stackoverflow 异常。来自 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());
    }
}

最佳答案

BeginReceive 注册与重叠 IO 操作关联的回调函数。当数据可用时,操作系统将调用回调,但 BeginReceive 调用会立即返回,因此您对 ReceiveCallback 的调用也会完成。
将实际 IO 视为发生在不属于您的线程中,而是发生在操作系统中。您注册回调的行为只是说“有事发生时继续调用我”,但它不会被添加到堆栈中。这就是它被称为异步的原因。

关于.net - 为什么在 .Net 中使用异步编程模型不会导致 StackOverflow 异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4692283/

相关文章:

c# - "stringDemo"与新字符串("stringDemo".ToCharArray);

C# 将 mdb 归档数据类型更改为 memo 并保存

c# - 将十六进制字符串转换为动态原始类型

java - 异步任务未加载数据

multithreading - Lwt.async() 未按预期工作

c# - 异步 TCP 服务器/客户端不可靠数据包?

C# - ScheduledTasks 类 - 如何指定 localhost?

c# - 为什么 CLR 允许改变装箱的不可变值类型?

c# - 异步编程和虚函数

winapi - 如果 CancelIo 失败怎么办?