[英]MemoryMappedFile CreateViewAccessor throws “Not enough storage is available to process this command.”
我们在MemoryMappedFile中加载了一个222MB的文件,用于原始数据访问。 使用write方法更新此数据。 经过一些计算后,数据应重置为文件的原始值。 我们目前通过部署类并创建新实例来实现这一点。 这种情况很好,但有时CreateViewAccessor崩溃时出现以下异常:
System.Exception:没有足够的存储空间来处理此命令。 ---> System.IO.IOException:没有足够的存储空间来处理此命令。
at System.IO .__ Error.WinIOError(Int32 errorCode,String maybeFullPath)在System.IO.MemoryMappedFiles.MemoryMappedFile.CreateViewAccessor的System.IO.MemoryMappedFiles.MemoryMappedView.CreateView(SafeMemoryMappedFileHandle> memMappedFileHandle,MemoryMappedFileAccess访问,Int64偏移,Int64大小)处。 Int64偏移量,Int64>大小,MemoryMappedFileAccess访问权限)
以下类用于访问memorymapped文件:
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));
}
}
导致此问题的可能原因是什么?是否有解决方案/解决方法?
尝试使用x64平台并处理x32平台
确保每次都手动处理MemoryMapAccessor。 根据你的实现,GC 不会为你调用Dispose - 这里有很好的解释它正确使用IDisposable接口
调用Dispose不会使您的变量为null,因此GC将等到它理解没有人使用这些变量。 在Dispose之后确保您的变量超出范围,或者只是将它们标记为null。 最简单的情况是在您的Dispose中处理 - 如果您不再需要它们,为什么不将变量标记为null? 这允许GC更快地吃它们。
这是关于此类错误的另一个好主题(虽然它被称为VS.Net IDE,它包含可能发生此类错误的详细信息) 在VisualStudio 2008中没有足够的存储空间可用于处理此命令。如果您经常需要非常大的部件内存,这会导致内存碎片,所以很快你仍然有足够的总可用内存,你没有足够大的可用内存块。
对于您的具体情况,也许将文件中的byte[]
数组读入内存可能是一个美食的想法,尽管不会深入涉及非托管资源。 通过一些幸运的编码,它可以通过CLR实现更好的内存管理; 但你需要谨慎做出这样的决定。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.