我正在使用MaxMind.Db.Reader类来访问GeoLite2-City.mmdb文件,并且我在读取器上调用dispose后对文件执行某些操作时遇到文件访问问题。
重现此问题的最简单方法是使用一个控制台应用程序,类似于MaxMind.Db.Benchmark项目,该项目有一个Reader类的静态实例,在我的例子中称为_cityReader。
现在,如果你将_cityReader变量设置为一个新的Reader实例,然后调用它上面的dispose(我也将它设置为null)然后移动文件(移动工作正常)然后调用文件上的删除' s在新位置,您将在删除操作中获得UnauthorizedAccessException ...
_cityReader = new Reader(@"C:\temp\MaxMind\Active\GeoLite2-City.mmdb", FileAccessMode.MemoryMapped);
_cityReader.Dispose();
_cityReader = null;
File.Move(@"C:\temp\MaxMind\Active\GeoLite2-City.mmdb", @"C:\temp\MaxMind\Active\GeoLite2-CityMoved.mmdb");
File.Delete(@"C:\temp\MaxMind\Active\GeoLite2-CityMoved.mmdb");
我发现如果我使用反射来调用Disc the _cityReader._stream.Value属性,那么在此方案中,在调用_cityReader变量本身上的dispose之前,该文件将删除...
_cityReader = new Reader(@"C:\temp\MaxMind\Active\GeoLite2-City.mmdb", FileAccessMode.MemoryMapped);
FieldInfo field = typeof(Reader).GetField("_stream", BindingFlags.NonPublic | BindingFlags.Instance);
ThreadLocal<Stream> fieldValue = (ThreadLocal<Stream>)field.GetValue(_cityReader);
fieldValue.Value.Dispose();
_cityReader.Dispose();
_cityReader = null;
File.Move(@"C:\temp\MaxMind\Active\GeoLite2-City.mmdb", @"C:\temp\MaxMind\Active\GeoLite2-CityMoved.mmdb");
File.Delete(@"C:\temp\MaxMind\Active\GeoLite2-CityMoved.mmdb");
但是,除此之外,我实际上将静态读取器对象放在与其创建的线程不同的线程上,并发现即使在该场景下使用反射做这一点也意味着我仍然得到UnauthorizedAccessException。在这种情况下,我发现在处理_cityReader变量并将其设置为null后,我需要强制执行垃圾收集。为了重现这个,我在控制台应用程序中有一个静态方法,就像这样......
private static void DisposeReaderAndSwitchFiles()
{
_cityReader.Dispose();
_cityReader = null;
GC.Collect();
// Try switching files
File.Move(@"C:\temp\MaxMind\Active\GeoLite2-City.mmdb", @"C:\temp\MaxMind\Active\GeoLite2-CityMoved.mmdb");
File.Delete(@"C:\temp\MaxMind\Active\GeoLite2-CityMoved.mmdb");
}
然后在控制台应用程序的主要方法中我有这个......
_cityReader = new Reader(@"C:\temp\MaxMind\Active\GeoLite2-City.mmdb", FileAccessMode.MemoryMapped);
Thread t = new Thread(DisposeReaderAndSwitchFiles);
t.Start();
t.Join();
Console.WriteLine("Press Any Key To Continue...");
Console.ReadKey();
因此代码示例将起作用,但如果我从DisposeReaderAndSwitchFiles方法中删除GC.Collect()调用,则会收到UnauthorizedAccessException。
是否还有其他人遇到与MaxMind.Db.Reader对象类似的问题?
我做错了什么或我应该做的其他事情?感觉有点脏,迫使垃圾收集,如果可能的话我宁愿避免它。
谢谢,
菲尔
答案 0 :(得分:0)
我遇到的问题并不完全相似,但仍然存在访问问题。你可以在这里找到它。 Exception while accessing maxmind's GeoIP-country.mmdb database through hive