我想实现从 a 读取的异步读取,Stream
直到找到特定的终止字节。我真的不知道在找到给定字节之前我必须阅读多长时间,我想避免让线程等待结果。其他东西稍后会读取相同的流,这意味着我不能在终止字节之后读取太远。
到目前为止,我已经使用BeginRead
andEndRead
函数对和递归AsyncCallback
. 这很好用,但我有点担心如果长度很长,这将如何扩展,因为如果所有读取同步完成,它有时会产生相当令人印象深刻的调用堆栈。
public void ReadUntilSpecificByte(Stream stream, byte terminator, Action<byte[]> onComplete)
{
var output = new List<byte>();
var buffer = new byte[1];
Action[] readAction = { null };
readAction[0] = () => stream.BeginRead(buffer, 0, 1, asyncResult =>
{
stream.EndRead(asyncResult);
if (buffer[0] == terminator)
{
onComplete(output.ToArray());
}
else
{
output.Add(buffer[0]);
readAction[0]();
}
}, stream);
readAction[0]();
}
我是否在担心可能不是问题的事情,或者这是否可以以更智能的方式编写,以在更多的堆栈空间中运行?不幸的是,我不能使用 c# 4.5,我认为这会使这项任务更加顺利。流本身通常是 aNetworkStream
或 a SslStream
。
编辑:我采用了 Marc 建议的方法,并为所有读取做了一个内部缓冲区,保持 2k 缓冲区。这是一个可行的解决方案,可能会更好地利用潜在的昂贵读取,因为它总是从底层套接字读取尽可能多的内容。如果可以避免这种情况仍然会很酷,但我想这是完全异步的代价的一部分。