这是异步读取吗?

本文关键字:读取 异步 | 更新日期: 2023-09-27 18:12:41

我有一个listen()函数,它读取网络流和一个回调函数newDataRecievedCallback。

我调用BeginRead方法,这是Async,但我再次调用回调函数中的相同方法。这不是同步逻辑吗?

还有别的方法吗?

    private void listen()
    {
        networkStream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(newDataRecievedCallback), null);
    }
    private void newDataRecievedCallback(IAsyncResult rst)
    {
        try
        {
            int recievedDataSize = tcpClient.Client.Receive(buffer);
            recievedData = convertToString(buffer, incomeDataSize);
            //End Read
            networkStream.EndRead(rst);
            cleanBuffer();
            parseXMLData(recievedData);
            //Hier I call the same async method
            networkStream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(newDataRecievedCallback), null);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

这是异步读取吗?

如果 BeginRead 总是异步完成,那么在回调中再次调用它仍然是异步的。

然而,BeginRead有时会同步完成(检查IAsyncResult.CompletedSynchronously),因此当您不幸时,您的代码容易受到堆栈溢出的影响。例如,这可能发生在一个线程中:newDataRecievedCallback -> BeginRead -> newDataRecievedCallback -> BeginRead等等。

使用BeginRead的正确方法是使用类似于下面的模式(这是来自c# 4.0的代码片段)。实际上,您应该始终检查方法是否同步完成,然后采取适当的行动。

void Read()            // Read in a nonblocking fashion.
{
  while (true)
  {
    IAsyncResult r = _stream.BeginRead
     (_data, _bytesRead, _data.Length - _bytesRead, ReadCallback, null);
    // This will nearly always return in the next line:
    if (!r.CompletedSynchronously) return;   // Handled by callback
    if (!EndRead (r)) break;
  }
  Write();
}
void ReadCallback (IAsyncResult r)
{
  try
  {
    if (r.CompletedSynchronously) return;
    if (EndRead (r))
    {
      Read();       // More data to read!
      return;
    }
    Write();
  }
  catch (Exception ex) { ProcessException (ex); }
}
bool EndRead (IAsyncResult r)   // Returns false if there’s no more data
{
  int chunkSize = _stream.EndRead (r);
  _bytesRead += chunkSize;
  return chunkSize > 0 && _bytesRead < _data.Length;   // More to read
}

它仍然是异步的,因为你对networkStream.BeginRead的调用没有阻塞。您进行调用,然后退出该函数。是的,它将被再次调用,但仍然以异步方式。

还有别的办法吗?是的,有上百种方法。你的代码不错。这看起来有点紧密耦合,因为异步处理程序在处理数据的同时也在执行自己的管理。一个更简洁的方法是有某种类型的控制器,你的newDataRecievedCallback将通过委托通知,并将数据传递给它进行处理。控制器还将负责生成下一个异步进程。一个单独的控制器也可以传递接收到的数据进行处理,而不会阻塞更多的异步调用。