1

嗨,我有一个小问题,我正在使用套接字,我发现许多无限递归的情况参见来源: http: //pastebin.com/Cbd2Z2uE

问题是这样的:

private static void ReceiveCallback(IAsyncResult ar)
{
    ....
    // receive again
    socket.BeginReceive(state.Buffer,
        0,
        StateObject.BufferSize,
        0,
        ReceiveCallback,
    state);

    ....
}

所以我们有一个以递归方式再次调用的异步函数。这里我们的堆栈有问题?更清楚地说,这种情况没问题,递归也没问题,问题和问题是:在这种情况下,我会遇到stackoverflow的问题吗?

谢谢

4

2 回答 2

3

您没有递归(或处于危险或递归)。您只是在 IO 竞争端口接收到要处理的数据时安排要执行的回调(检查源代码以查看此内容)。当您的函数在当前线程上运行时,这不会发生,因为同一个线程必须通过轮询检查 IO 端口上的消息,否则另一个工作线程将一起运行您的函数。在任何一种情况下,您都不会递归或有递归的危险,因此堆栈不会爆炸(socket.BeginReceive应该立即返回并且不会在其中调用您的函数)。

我相信您正在查看此页面上显示的场景 14,但它可能是之前的场景,因为您的控制台应用程序具有消息泵。但最重要的是,您的应用程序中没有实际的函数递归(或支持它使用的 OS 框架功能)。

于 2013-09-28T09:02:00.550 回答
2

ReceiveCallback被框架代码调用,除非你直接调用它。 BeginReceive将指定的委托存储为回调函数,此时不调用委托。

例如,我添加了一些代码来获取堆栈跟踪:

private static void ReceiveCallback(IAsyncResult ar)
{
    Console.WriteLine(Environment.StackTrace);
    // retrieve the state and socket

并得到:

at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
at System.Environment.get_StackTrace()
at Program.ReceiveCallback(IAsyncResult ar) in r:\Temp\LINQPad\aqwfvqfb\query_ettlka.cs:line 102
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.ContextAwareResult.CompleteCallback(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Net.ContextAwareResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

并且即使您调用它也会显示BeginReceive出来ReceiveCallback

于 2013-09-28T09:14:57.623 回答