Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 内存映射文件从内存中删除_C#_Memory_Mutex - Fatal编程技术网

C# 内存映射文件从内存中删除

C# 内存映射文件从内存中删除,c#,memory,mutex,C#,Memory,Mutex,出于某种原因,当我从一个内存映射文件中读取几次时,它只是从内存中随机删除,我不知道发生了什么。是内核还是GC从内存中删除它?如果是,我如何防止他们这样做 我正在将一个对象序列化为Json并将其写入内存 我在几次尝试再次读取时遇到异常,我得到FileNotFoundException:找不到指定的文件。 private const String Protocol = @"Global\"; 要写入内存映射文件的代码: public静态布尔WriteToMemoryFile(列表数据) { 尝试

出于某种原因,当我从一个内存映射文件中读取几次时,它只是从内存中随机删除,我不知道发生了什么。是内核还是GC从内存中删除它?如果是,我如何防止他们这样做

我正在将一个对象序列化为Json并将其写入内存

我在几次尝试再次读取时遇到异常,我得到
FileNotFoundException:找不到指定的文件。

private const String Protocol = @"Global\";
要写入内存映射文件的代码:
public静态布尔WriteToMemoryFile(列表数据)
{
尝试
{
如果(数据==null)
{
抛出新ArgumentNullException(“数据不能为null”,“数据”);
}
var mapName=typeof(T).FullName.ToLower();
var mutexName=Protocol+typeof(T).FullName.ToLower();
var serializedData=JsonConvert.SerializeObject(数据);
var容量=序列化数据长度+1;
var mmf=MemoryMappedFile.CreateOrOpen(映射名,容量);
var IsMutDecated=假;
var mutex=新的互斥体(true,mutexName,out ismutexated);
如果(!未排泄)
{
var isMutexOpen=false;
做
{
isMutexOpen=mutex.WaitOne();
}
而(!isMutexOpen);
var streamWriter=newstreamwriter(mmf.CreateViewStream());
streamWriter.WriteLine(序列化数据);
streamWriter.Close();
mutex.ReleaseMutex();
}
其他的
{
var streamWriter=newstreamwriter(mmf.CreateViewStream());
streamWriter.WriteLine(序列化数据);
streamWriter.Close();
mutex.ReleaseMutex();
}
返回true;
}
捕获(例外情况除外)
{
返回false;
}
}
要从内存映射文件中读取的代码:
公共静态列表ReadFromMemoryFile()
{
尝试
{
var mapName=typeof(T).FullName.ToLower();
var mutexName=Protocol+typeof(T).FullName.ToLower();
var mmf=MemoryMappedFile.OpenExisting(映射名);
var mutex=mutex.OpenExisting(mutexName);
var isMutexOpen=false;
做
{
isMutexOpen=mutex.WaitOne();
}
而(!isMutexOpen);
var streamReader=newstreamreader(mmf.CreateViewStream());
var serializedData=streamReader.ReadLine();
streamReader.Close();
mutex.ReleaseMutex();
var data=JsonConvert.DeserializeObject(serializedData);
mmf.Dispose();
返回数据;
}
捕获(例外情况除外)
{
返回默认值(列表);
}
}

创建内存映射文件的进程必须保留对该文件的引用,只要您希望它存在。正是由于这个原因,使用
CreateOrOpen
有点棘手-您不知道处理内存映射文件是否会破坏它

通过将显式的
mmf.Dispose()
添加到
writeMemoryFile
方法中,您可以很容易地看到这一点,它将完全关闭文件。
Dispose
方法在
mmf
实例的所有引用退出范围后的某个时间从终结器调用

或者,为了更清楚地表明GC是罪魁祸首,您可以尝试显式调用GC:

WriteToMemoryFile("Hi");
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();  
ReadFromMemoryFile().Dump(); // Nope, the value is lost now
请注意,我稍微更改了您的方法以处理简单字符串;您确实希望生成尽可能简单的代码,以再现您观察到的行为。即使只需要获取
JsonConverter
也是一个不必要的复杂问题,可能会导致人们甚至不尝试运行您的代码:)


另外,在执行
Mutex.WaitOne
时,您需要检查是否存在
放弃mutexception
——这不是失败,它意味着您接管了Mutex。大多数应用程序处理这个错误,导致死锁以及互斥锁所有权和生存期的问题:)换句话说,将
放弃mutexception
视为成功。哦,最好在
finally
子句中放入
Mutex.ReleaseMutex
这样的内容,以确保它确实发生,即使您遇到异常。线程或进程死机并不重要(这只会导致另一个contendants获取
放弃的MutexException
),但如果您仅获取一个异常,并使用
返回false“处理”,除非您关闭所有应用程序并重新启动,否则互斥锁将不会释放:)

显然,问题在于,正如Luaan所解释的,MMF失去了上下文。但仍然没有人解释如何执行:

  • “写入MMF文件”代码必须在单独的异步线程上运行
  • 一旦读取完成,代码“从MMF读取”将通知MMF已被读取。例如,通知可以是文件中的标志

  • 因此,只要从第二部分读取MMF文件,运行“写入MMF文件”的异步线程就会运行。因此,我们创建了内存映射文件有效的上下文。

    能否添加发生异常的行?您有哪些调用顺序
    WriteMemoryFile
    ReadFromMemoryFile
    ?您是否意识到,
    mmf.Dispose()
    会释放
    内存映射文件
    ?我调用Dispo
    public  static  List<T>                     ReadFromMemoryFile<T>()
            {
                try
                {
                    var mapName = typeof(T).FullName.ToLower();
                    var mutexName = Protocol + typeof(T).FullName.ToLower();
    
                    var mmf = MemoryMappedFile.OpenExisting(mapName);
                    var mutex = Mutex.OpenExisting(mutexName);
                    var isMutexOpen = false;
                    do
                    {
                        isMutexOpen = mutex.WaitOne();
                    }
                    while (!isMutexOpen);
    
                    var streamReader = new StreamReader(mmf.CreateViewStream());
                    var serializedData = streamReader.ReadLine();
                    streamReader.Close();
                    mutex.ReleaseMutex();
                    var data = JsonConvert.DeserializeObject<List<T>>(serializedData);
                    mmf.Dispose();
                    return data;
                }
                catch (Exception ex)
                {
                    return default(List<T>);
                }
    
            }
    
    WriteToMemoryFile("Hi");
    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();  
    ReadFromMemoryFile().Dump(); // Nope, the value is lost now