这是异步读数吗?

时间:2011-10-30 01:54:20

标签: c#

我有一个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);
        }
    }

2 个答案:

答案 0 :(得分:4)

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

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

使用BeginRead的正确方法是使用类似于下面的模式(这是一个来自C#4.0的Nutshell中的code snippet)。实质上,您应该始终检查方法是否同步完成,然后采取适当的行动。

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
}

答案 1 :(得分:3)

它仍然是异步的,因为您对networkStream.BeginRead的调用不会阻止。您拨打电话然后退出该功能。是的,它会被再次调用,但仍然是异步的。

还有其他方法吗?是的,有数百种方式。你的代码还不错。它似乎有点紧密耦合,因为您的异步处理程序正在执行自己的管理以及处理数据。更简洁的方法是使用newDataRecievedCallback通过委托通知的某种控制器,并将数据传递给它进行处理。控制器还将负责产生下一个异步过程。单独的控制器也可以传递接收的数据进行处理,而不会阻止更多的异步调用。