我想实现从Stream
读取的异步读取,直到找到特定的终止字节。我真的不知道在找到给定字节之前我必须阅读多长时间,并且我想避免让线程等待结果。其他东西稍后将读取相同的流,这意味着在终止字节之后我无法读得太远。
到目前为止,我已使用BeginRead
和EndRead
函数对以及递归AsyncCallback
来管理此问题。这很好用,但我有点担心如果长度很长,它会如何缩放,因为如果所有读取同步完成,它有时会产生相当令人印象深刻的callstack。
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,我认为这会使这项任务变得更加顺畅。流本身通常是NetworkStream
或SslStream
。
编辑:我采用了Marc建议的方法,为所有读取做了内部缓冲,保持2k缓冲区。这是一个可行的解决方案,可能更好地利用可能昂贵的读取,因为它总是会从底层套接字中读取尽可能多的内容。如果可以避免这种情况仍然会很酷,但我想这是完全异步的价格的一部分。