0

在 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...
  }

  ...
}
4

3 回答 3

1

首先我想提一下,这个问题类似于这如何不会导致堆栈溢出?.

现在具体谈谈您的问题:代码片段使用的线程数受用于执行的线程池中可用线程数的限制ReceiveAsync。如果返回了对 async 方法的先前调用,则只会生成新线程。

每次都OnDataReception更进一步。而是不直接调用. 这意味着,这两种方法之间没有直接的函数递归。在后台线程中执行不会产生嵌套的堆栈帧。ListenForDataListenForDataOnDataReceptionReceiveAsync

所以在我看来,代码中没有隐藏的递归。

于 2014-01-06T10:22:26.777 回答
1

根据MSDN 文档Socket.ReceiveAsync

如果 I/O 操作处于挂起状态,则返回 true 。e参数上的 SocketAsyncEventArgs.Completed事件将在操作完成后引发。

如果 I/O 操作同步完成,则返回 false 。在这种情况下, 不会引发eSocketAsyncEventArgs.Completed参数上的事件,并且可以在方法调用返回后立即检查作为参数传递的e对象以检索操作结果。

要回答您的问题,,它不会创建无限循环/递归。

您的ListenForData方法每次调用只会调用OnDataReception一次ReceiveAsync. 由于您是在调用ListenForDataOnDataReception不是在循环中,因此它将如下所示:

ListenForData called!
(time elapses)
OnDataReception called!
ListenForData called!
(time elapses)
OnDataReception called!
ListenForData called!
...

这几乎与 using 相同,在回调中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);
}
于 2014-01-07T22:44:03.463 回答
0

这不会产生任何无限递归,但您可以稍微更改架构以有效利用资源。您可以使用两个不同的线程进行侦听和转换,因为程序需要侦听端口而与转换结果无关。

于 2014-01-06T13:40:20.690 回答