2013-03-27 189 views
4

我们正在加载一个用于原始数据访问的MemoryMappedFile中的222MB文件。该数据使用写入方法进行更新。经过一些计算后,数据应重置为文件的原始值。我们目前正在通过处理这个类并创建一个新实例来做到这一点。 这远远很多次了,但有时CreateViewAccessor与以下异常崩溃:MemoryMappedFile CreateViewAccessor抛出“没有足够的存储可用于处理此命令。”

System.Exception的:没有足够的存储是可用来处理此命令。 ---> System.IO.IOException:没有足够的存储可用于处理此命令。

在System.IO .__ Error.WinIOError(的Int32的errorCode,字符串maybeFullPath) 在System.IO.MemoryMappedFiles.MemoryMappedView.CreateView(SafeMemoryMappedFileHandle> memMappedFileHandle,MemoryMappedFileAccess访问,Int64的偏移,Int64的大小) 在System.IO。 MemoryMappedFiles.MemoryMappedFile.CreateViewAccessor(Int64的偏移量,Int64类型>大小,MemoryMappedFileAccess访问)

下面的类被用于访问存储器映射的文件:

public unsafe class MemoryMapAccessor : IDisposable 
{ 
    private MemoryMappedViewAccessor _bmaccessor; 
    private MemoryMappedFile _mmf; 
    private byte* _ptr; 
    private long _size; 

    public MemoryMapAccessor(string path, string mapName) 
    { 
     FileInfo info = new FileInfo(path); 
     _size = info.Length; 

     using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite)) 
      _mmf = MemoryMappedFile.CreateFromFile(stream, mapName, _size, MemoryMappedFileAccess.Read, null, HandleInheritability.None, false); 

     _bmaccessor = _mmf.CreateViewAccessor(0, 0, MemoryMappedFileAccess.CopyOnWrite); 
     _bmaccessor.SafeMemoryMappedViewHandle.AcquirePointer(ref _ptr); 
    } 

    public void Dispose() 
    { 
     if (_bmaccessor != null) 
     { 
      _bmaccessor.SafeMemoryMappedViewHandle.ReleasePointer(); 
      _bmaccessor.Dispose(); 
     } 
     if (_mmf != null) 
      _mmf.Dispose(); 
    } 


    public long Size { get { return _size; } } 

    public byte ReadByte(long idx) 
    { 
     if ((idx >= 0) && (idx < _size)) 
     { 
      return *(_ptr + idx); 
     } 

     Debug.Fail(string.Format("MemoryMapAccessor: Index out of range {0}", idx)); 
     return 0; 
    } 

    public void Write(long position, byte value) 
    { 
     if ((position >= 0) && (position < _size)) 
     { 
      *(_ptr + position) = value; 
     } 
     else 
      throw new Exception(string.Format("MemoryMapAccessor: Index out of range {0}", position)); 
    } 
} 

这个问题有什么可能的原因,有没有解决方法/解决方法?

+0

你试过在处理MMF后调用'GC.Collect'吗?那个错误通常意味着没有足够的内存。 – 2013-03-27 15:48:50

+0

我们已经写完了我们自己的映射器,它将这个文件的块加载到内存中,因此不需要在内存中有一大块可用空间。你可以查看https://gist.github.com/luuksommers/af473efe618d589df951 – Luuk 2015-03-06 09:47:03

回答

5
  • 尝试使用x64平台过程,而不是X32的人

  • 确保您手动配置MemoryMapAccessor每次。根据您的实现,GC将调用Dispose你 - 这里是关于它的Proper use of the IDisposable interface

  • 调用Dispose不会使你变空很好的解释,所以GC会等到明白没有人使用这些变量。确保您的变量在Dispose之后超出范围,或者将它们标记为空。最简单的情况是在你的Dispose中处理 - 为什么不将变量标记为空,如果你不再需要它们?这使GC可以更快地吃掉它们。

  • 下面是关于这样的错误(虽然被称为VS.Net IDE,它包含的细节,为什么会发生这样的错误)Not enough storage is available to process this command in VisualStudio 2008一个想法,如果你经常需要的内存非常大的部分,这导致另一个很好的话题内存碎片,尽管您仍然拥有足够的可用内存,但您没有足够大的可用内存空间。

  • 对于您的具体情况,从文件读取byte[]数组到内存中,但不涉及非托管资源,也许只是一个美食想法。通过一些幸运的编码,可能会导致CLR更好的内存管理;但你需要谨慎做出这样的决定。

+1

谢谢,这里有很多很好的信息!我会尝试一些东西并回复你。 – Luuk 2013-03-28 11:56:18

相关问题