gpt4 book ai didi

c# - 内存映射文件从内存中删除

转载 作者:IT王子 更新时间:2023-10-28 23:38:13 24 4
gpt4 key购买 nike

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

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

几次后尝试再次读取时出现异常,我得到 FileNotFoundException: Unable to find the specified file.

private const String Protocol = @"Global\";

写入内存映射文件的代码:

public  static  Boolean                 WriteToMemoryFile<T>(List<T> data)
{
try
{
if (data == null)
{
throw new ArgumentNullException("Data cannot be null", "data");
}

var mapName = typeof(T).FullName.ToLower();
var mutexName = Protocol + typeof(T).FullName.ToLower();
var serializedData = JsonConvert.SerializeObject(data);
var capacity = serializedData.Length + 1;

var mmf = MemoryMappedFile.CreateOrOpen(mapName, capacity);
var isMutexCreated = false;
var mutex = new Mutex(true, mutexName, out isMutexCreated);
if (!isMutexCreated)
{
var isMutexOpen = false;
do
{
isMutexOpen = mutex.WaitOne();
}
while (!isMutexOpen);
var streamWriter = new StreamWriter(mmf.CreateViewStream());
streamWriter.WriteLine(serializedData);
streamWriter.Close();
mutex.ReleaseMutex();
}
else
{
var streamWriter = new StreamWriter(mmf.CreateViewStream());
streamWriter.WriteLine(serializedData);
streamWriter.Close();
mutex.ReleaseMutex();
}
return true;
}
catch (Exception ex)
{
return false;
}
}

从内存映射文件中读取的代码:

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>);
}

}

最佳答案

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

您可以通过将显式 mmf.Dispose() 添加到您的 WriteToMemoryFile 方法中轻松看到这一点 - 它会完全关闭文件。 Dispose 方法从 mmf 实例的终结器调用,一段时间后对它的所有引用都退出范围。

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

WriteToMemoryFile("Hi");
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
ReadFromMemoryFile().Dump(); // Nope, the value is lost now

请注意,我稍微更改了您的方法以使用简单的字符串;你真的想要生成最简单可能的代码来重现你观察到的行为。即使只需要获取 JsonConverter 也是不必要的复杂性,并且可能会导致人们甚至不尝试运行您的代码:)

作为旁注,您希望在执行 Mutex.WaitOne 时检查 AbandonedMutexException - 这不是失败,这意味着您接管了互斥锁.大多数应用程序都会处理这个错误,导致死锁以及互斥体所有权和生存期问题:) 换句话说,将 AbandonedMutexException 视为成功。哦,最好将 Mutex.ReleaseMutex 之类的内容放在 finally 子句中,以确保它确实发生,即使您遇到异常也是如此。线程或进程死亡无关紧要(这只会导致其他竞争者之一得到 AbandonedMutexException),但如果你只是得到一个异常,你会用 return false; ,在您关闭所有应用程序并重新开始之前,互斥锁不会被释放:)

关于c# - 内存映射文件从内存中删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29962939/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com