在Marc Gravell的blog post主题中对管道进行了精彩的介绍之后,我正在修补实现带有套接字的管道。
我知道Marc已经提出Pipelines.Sockets.Unofficial ,我将其用作参考,但是我有一个问题。
似乎SocketAsyncEventArgs
对SetBuffer()
方法有新的重载:SetBuffer(Memory<byte>)
似乎这里的目的是与Pipes很好地集成。
我的困惑是由于Pipe.Reader.ReadAsync()
返回包含ReadResult
(ReadOnlySequence<byte>
)的ReadResult.Buffer
在Buffer.IsSingleSegment == true
的情况下,很明显该怎么做:
SocketAsyncEventArgs.SetBuffer(Buffer[0])
但是在有多个细分的情况下,我不能完全确定最佳做法是什么。
我当然可以从管道中获取一个byte[]
并完成它,但这会产生一个副本(甚至可能有多个副本)。
此处ReadOnlySequence<byte>
的用途是什么?有没有办法获取表示序列全部内容的“内存”?
也许我需要重新阅读Marc的博客文章...
答案 0 :(得分:1)
对于我所看到的:
有这个ReadOnlySequence<>.First
,在IsSingleSegment
的情况下,应该会为您提供ReadOnlyMemory<>
。
对于具有更多细分的序列,我认为您应该使用
var iSegment = seq.Start;
ReadOnlyMemory<byte> readMemory;
while(seq.TryGet(ref iSegment, out readMemory, advance: true))
{ /* do smth */ }
或者,我认为这也做同样的事情:
foreach(var memory in seq)
{ /* do smth */ }
如果您关心性能并且不想复制整个缓冲区(那就是.ToArray()扩展方法所做的事情),则可以进行遍历。
恕我直言的目的是有效地表示非连续缓冲区。
我不确定Sequence<>
的实现细节,但是在大多数缓冲方案中,通常都持有几个小缓冲区(3,2)并在它们之间进行切换,以免不必要地分配新的内存。有时抽象为“循环”或“环形”缓冲区。
这会导致Sequence<>
中的这种“顺序”内存访问模式。