嗨,我有一个小问题,我正在使用套接字,我发现许多无限递归的情况见来源:http://pastebin.com/Cbd2Z2uE
问题是这样的:
private static void ReceiveCallback(IAsyncResult ar)
{
....
// receive again
socket.BeginReceive(state.Buffer,
0,
StateObject.BufferSize,
0,
ReceiveCallback,
state);
....
}
所以我们有一个异步函数,它以递归的方式再次调用。在这里,我们的堆栈有问题吗?更清楚的是,这种情况还可以,递归也可以,问题和问题是:在这种情况下,我会遇到堆栈溢出的问题吗?
谢谢
您没有递归(或处于危险或递归)。您只需安排在 IO 竞争端口接收数据供您处理时执行回调(检查源代码以查看此内容)。当您的函数在当前线程上运行时,不会发生这种情况,因为同一线程必须通过轮询检查 IO 端口上的消息,或者另一个工作线程将一起运行您的函数。在任何一种情况下,您都不会递归或有回避的危险,因此堆栈不会爆炸(socket.BeginReceive
应该立即返回并且不会在其中调用您的函数)。
我相信您正在查看此页面上显示的方案 14,但这可能是以前的方案,因为您的控制台应用程序具有消息泵。但最重要的是,您的应用程序中没有实际的函数递归(或它使用的辅助操作系统框架功能)。
您的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:TempLINQPadaqwfvqfbquery_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)
甚至你用ReceiveCallback
打电话给BeginReceive
也显示.