在C#类中,以下格式用于异步读取套接字中的数据。
正如您在代码中看到的,它使用AsyncReceive
从套接字读取数据。它在收到数据时回拨OnDataReception
。
在OnDataReception
中,如果对话尚未完成,则处理收到的数据并再次调用ListenForData
。
此代码段是否会创建任何类型的无限递归? (功能或线程)
class ClientConnection{
Socket socket = ...
SocketAsyncEventArgs args = ...
args.Completed += new EventHandler<SocketAsyncEventArgs>(OnDataReception);
...
public void ListenForData(){
...
socket.ReceiveAsync(args);
...
}
public void OnDataReception(Object obj, SocketAsyncEventArgs args){
...
// if conversation is finished, return
// else call ListenForData() again...
}
...
}
答案 0 :(得分:1)
首先我想提一下,问题类似于How does this not cause a stack overflow?。
现在具体谈谈您的问题:代码片段使用的线程数量受用于执行ReceiveAsync
的线程池中可用线程数的限制。如果先前调用异步方法返回,则刚生成新线程。
进一步OnDataReception
每次都会调用ListenForData
。 ListenForData
而不是直接调用OnDataReception
。这意味着,两种方法之间没有直接的函数递归。在后台线程中执行的ReceiveAsync
不会产生嵌套的堆栈帧。
所以在我看来代码中没有隐藏的递归。
答案 1 :(得分:1)
每MSDN Documentation on Socket.ReceiveAsync
:
如果I / O操作处于挂起状态,则返回true 。该 将引发 e 参数上的
SocketAsyncEventArgs.Completed
事件 完成手术后。如果I / O操作,则返回false 同步完成。在这种情况下,The e 参数上的
SocketAsyncEventArgs.Completed
事件不会发生 引发并且可以检查作为参数传递的 e 对象 在方法调用返回后立即检索结果 操作。
要回答您的问题,否它不会创建无限循环/递归。
每次拨打ListenForData
时,您的OnDataReception
方法只会拨打ReceiveAsync
。由于您在ListenForData
中呼叫OnDataReception
而不是在循环中,它将如下所示:
ListenForData called!
(time elapses)
OnDataReception called!
ListenForData called!
(time elapses)
OnDataReception called!
ListenForData called!
...
这几乎与使用Socket.BeginReceive
相同,传递AsyncCallback
然后在回调中调用Socket.EndReceive
后跟另一个Socket.BeginReceive
。它是无限期循环,但不是无限循环。
请参阅:
void StartReceiving()
{
// Start receiving asynchronously...
socket.BeginReceive(recvBuffer, 0, recvBuffer.Length, SocketFlags.None, OnDataReceived, null);
}
void OnDataReceived(IAsyncResult result)
{
// Finish receiving this data.
var numberOfBytesReceived = socket.EndReceive(result);
// Start receiving asynchronously again...
if(numberOfBytesReceived > 0 && socket.Connected)
socket.BeginReceive(recvBuffer, 0, recvBuffer.Length, SocketFlags.None, OnDataReceived, null);
}
答案 2 :(得分:0)
这不会产生任何无限期的递归,但您可以稍微更改架构以获得有效的资源利用率。 您可以使用两个不同的线程进行监听和转换,因为无论转换结果如何,程序都需要监听端口。