这是异步读取吗?
本文关键字:读取 异步 | 更新日期: 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
将通过委托通知,并将数据传递给它进行处理。控制器还将负责生成下一个异步进程。一个单独的控制器也可以传递接收到的数据进行处理,而不会阻塞更多的异步调用。