我怎样才能在C#stream中进入非托管内存流?

Rab*_*bit 4 c# memory performance unmanaged stream

我可以使用UnmanagedMemoryStream在C#中读取非托管内存,但是我该怎么做呢?

我想从托管流直接读入非托管内存,而不是先读取一个byte []然后再复制.我正在对大量请求进行异步流读取,因此增加的内存很重要(更不用说附加副本).

Gre*_*g D 5

如果您有一个已知的目标缓冲区并且您知道数据有多大,那么这实际上并不太难.重要的实现是,UnmanagedMemoryStream只是一个本机字节序列的薄包装器.

你想要做的是以通常的方式获取指向本机目标缓冲区的指针.然后你可以在它上面构造一个可写的 UnmanagedMemoryStream.将源流复制到目标流并瞧!单个副本已将您从托管内存世界转移到本机内存世界.在C++/CLI中,它看起来像这样:

void CopyStreamToNativePtr(Stream^ src, unsigned char* dst)
{
    // Assuming we want to start the copy at the beginning of src
    src->Seek(0, SeekOrigin::Begin);

    // Create an UnmanagedMemoryStream on top of the destination
    // with an appropriate size and capacity (We assume the buffer is
    // is sized to the source data in this function!)
    UnmanagedMemoryStream target(dst, src->Length, src->Length, FileAccess::Write);

    // Copy to your heart's content!
    src->CopyTo(%target);

    // We made the UnmanagedMemoryStream local so that we wouldn't have
    // to explicitly Dispose() of it.
}
Run Code Online (Sandbox Code Playgroud)

  • 如何仅将特定数量的字节从一个流复制到另一个流?src->CopyTo 将复制整个流。我只想复制n个字节。 (2认同)

Pet*_*ete 2

我认为这实际上是不可能的。当您谈论托管流时,我想您指的是 System.IO.Stream 或其子类的实例。

该类的成员以 byte[] 作为参数,这是一个托管类。

我猜你能想到的最接近的方法是创建一个托管 byte[],然后在不安全的块中创建一个 byte*,然后将 byte* 传递给任何需要非托管引用的地方:

unsafe function test()
{
    var buffer = new byte[1024];
    fixed (byte* bufferPtr = &buffer[0])
    {   
        // Read bytes and pass the ptr to a function that needs to
        // operate on data directly 
    }
}
Run Code Online (Sandbox Code Playgroud)

但这并不完全是你所要求的

编辑:不过要小心。您提到了有关异步读取的内容。一旦超出固定边界,GC 可能会在内存中移动数组。如果您将指针传递给某个继续在不同线程中运行的“不安全”函数,则该指针将指向无效的内存位置。