如何解决如何执行'Memory<T>'到'Stream'的最小分配转换?
框架中似乎不存在将 Memory<T>
实例转换为 Stream
的原生方式。是否有一种简单的方法可以使用一些仅使用来自 Memory<T>
实例的实际内存的无分配方法来实现这一点,或者可能是一种仅利用最小缓冲区的方法?
我找不到任何从 Memory<T>
到 Stream
的示例:只有相反的情况很常见,因为 Stream
上有几个较新的重载允许处理 {{1} } 实例。
似乎很直观,以至于人们可以从 Memory<T>
转换为 Memory<>
(不可否认,主要是因为它们的名字)所以我有点失望地发现事实并非如此。
我也找不到任何简单的方法来创建带有 MemoryStream
的 System.IO.Pipelines
PipeReader
或 PipeWriter
,因为它们具有 Memory<T>
扩展名。
解决方法
您将需要使用不安全代码:
private static unsafe void DoUnsafeMemoryStuff<T>(ReadOnlyMemory<T> mem) where T : unmanaged
{
Stream stream;
MemoryHandle? memHandle = null;
GCHandle? byteHandle = null;
int itemSize = sizeof(T);
if (MemoryMarshal.TryGetArray(memory,out var arr))
{
byteHandle = GCHandle.Alloc(arr.Array,GCHandleType.Pinned);
int offsetBytes = arr.Offset * itemSize;
int totalBytes = arr.Count * itemSize;
int streamBytesRemaining = totalBytes - offsetBytes;
stream = new UnmanagedMemoryStream((byte*)byteHandle.Pointer + offsetBytes,streamBytesRemaining);
}
else
{
// common path,will be very fast to get the stream setup
memHandle = mem.Pin();
stream = new UnmanagedMemoryStream((byte*)memHandle.Pointer,mem.Length * itemSize);
}
// use stream like any other stream - you will need to keep your memory object and the handle object alive until your stream usage is complete
try
{
// do stuff with stream
}
finally
{
// cleanup
if (memHandle.HasValue) { memHandle.Value.Dispose(); }
if (byteHandle.HasValue) { byteHandle.Value.Free(); }
}
}
,
问题是,Memory<T>
可能实际上不是在查看数组:它可能正在使用 MemoryManager
,或者做其他事情。
也就是说,可以使用 MemoryMarshal.TryGetArray
来查看它是否确实引用了一个数组,如果是,则采用优化的路径:
ReadOnlyMemory<byte> memory = new byte[] { 1,2,3,4,5 }.AsMemory();
var stream = MemoryMarshal.TryGetArray(memory,out var arraySegment)
? new MemoryStream(arraySegment.Array,arraySegment.Offset,arraySegment.Count)
: new MemoryStream(memory.ToArray());
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。