MemoryMappedFile CreateViewAccessor throws "Not enough storage is available to process this command."

c#, memory-mapped-files

Solution

Try using x64 platform and process instead x32 ones

Ensure you dispose MemoryMapAccessor manually every time. According to your implementation, GC will not call Dispose for you - here is great explanation about it Proper use of the IDisposable interface

Calling Dispose does not make your variable null, so GC will wait until it understand no one using these variables. Make sure your variables go out of scope after Dispose, or simply mark them null. Easiest case is disposing in your Dispose - why not to mark variables as null if you don't need them anymore? This allows GC to eat them quicker.

Here is another good topic regarding such error (though is referred to VS.Net IDE, it contains details why such error may happen) Not enough storage is available to process this command in VisualStudio 2008 One of ideas if that you often need really big parts of memory, which results in memory fragmentation, so soon while you still have enough total free memory, you don't have big enough chunk of free memory.

For your specific case, maybe it will be a food idea to just read `byte[]` array into memory from file, though not deeply involving unmanaged resources. With some lucky coding it may results in better memory management by CLR; but you need to be caution with such decisions.

Problem

We're loading a 222MB file in a MemoryMappedFile for raw data access. This data is updated using the write method. After some calculations, the data should be reset to the original value of the file. We're currently doing that by disposing the class and creating a new instance. This goes well a lot of times, but sometimes the CreateViewAccessor crashes with the following exception: System.Exception: Not enough storage is available to process this command. ---> System.IO.IOException: Not enough storage is available to process this command. at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) at System.IO.MemoryMappedFiles.MemoryMappedView.CreateView(SafeMemoryMappedFileHandle > memMappedFileHandle, MemoryMappedFileAccess access, Int64 offset, Int64 size) at System.IO.MemoryMappedFiles.MemoryMappedFile.CreateViewAccessor(Int64 offset, Int64 > size, MemoryMappedFileAccess access) The following class is used to access the memorymapped file: ``` 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)); } } ``` What are the possible causes for this problem and is there any solution / workaround?

Original source