如何在内存映射文件中并行处理数据

时间:2013-05-03 04:46:35

标签: c# memory-mapped-files

正如内存映射文件的名称所示,我知道可以使用C#中的类MemoryMappedFile将大文件的一部分映射到内存以进行快速数据处理。我想对内存映射文件做的是并行处理映射的内存。为了做到这一点,我有以下问题

  1. MemoryMappedFileViewAccessor线程安全且Parallel.For-safe?我实际上制作了一个演示程序来测试这个问题,它似乎正在起作用。但是找不到任何关于此的参考。如果答案是肯定的,我就完成了。否则,
  2. 有没有办法直接访问与数组映射的内存?我知道MemoryMappedFileViewAccessor有ReadArray方法,但使用该方法是重复内存。

3 个答案:

答案 0 :(得分:10)

你可以说明这一点。内存映射文件只是程序中的一块内存,其字节可由多个进程访问。它们在托管代码中非常笨拙,因为这个块存在于特定地址。这需要使用指针访问数据,它们在托管代码中是禁忌。 MemoryMappedFileViewAccessor包装该指针,它将数据从托管内存复制到共享内存。请注意,这会破坏使用MMF的主要原因,以及为什么他们的支持需要花费很长时间才能显示在.NET中。请确保您不想使用命名管道。

因此推断出这一点,MMF肯定不是设计上的线程安全的,因为这是共享内存,就像代码中的全局变量一样。如果线程读取和写入共享内存的相同部分,则完全相同的方式出错。并且你必须保护完全相同,锁定以确保只有一个线程可以访问共享部分。

另请注意,您需要在读取和写入MMF的进程之间实现该锁定。这往往是痛苦的,您必须使用“主”进程创建的命名互斥锁,并打开“从属”进程。你不能吝啬锁定要求。值得注意的是,你从未在你的问题中提到过这样做,所以那里有红旗。

在一个进程中,不访问MMF的同一部分的线程不能相互进入。就像两个访问不同变量的线程一样,不需要任何同步。只要他们持有互斥锁,确保另一个进程无法写入该部分。请注意,这可能意味着您希望使用信号量来保护MMF访问,只能通过一个线程获取互斥锁。

答案 1 :(得分:3)

在内部,MemoryMappedViewAccessor派生自UnmanagedMemoryAccessor,它看起来是不可变的,虽然没有只读字段 - 至少它不会在读/写操作期间修改现有字段,这使得它是线程安全的。反过来,它从SafeBuffer类读取内存映射文件数据,其中包含comments header中的以下文本:

/* Keep the penalties for using this class small, both in terms of space 
// and time.  Having multiple threads reading from a memory mapped file
// will already require 2 additional interlocked operations.  If we add in 
// a "current position" concept, that requires additional space in memory and 
// synchronization.  Since the position in memory is often (but not always)
// something that can be stored on the stack, we can save some memory by 
// excluding it from this object.  However, avoiding the need for
// synchronization is a more significant win.  This design allows multiple
// threads to read and write memory simultaneously without locks (as long as
// you don't write to a region of memory that overlaps with what another 
// thread is accessing).

所以我的猜测是内存映射文件的操作是线程安全的,尽管奇怪的是在MSDN中没有确认这一点。

答案 2 :(得分:0)

1)MSDN声明MemoryMappedFileMemoryMappedViewAccessor

  

此类型的任何公共静态(在Visual Basic中为Shared)成员都是线程安全的。不保证任何实例成员都是线程安全的。

2)MemoryMappedFile的重点不是减少内存分配。如果您从磁盘读取文件,则必须分配内存来存储从文件中读取的项目。内存映射文件也是如此