title: MaxMind GeoIP Reader Dispose Issue - UnauthorizedAccessException on mmdb file following Reader.Dispose()
body: <p>I am using the MaxMind.Db.Reader class to access the GeoLite2-City.mmdb file and I am having file access issues performing certain actions on the file after calling dispose on the reader.</p>
  
  <p>The simplest way to reproduce this issue is to have a console application, similar to the MaxMind.Db.Benchmark project, which has a static instance of the Reader class, in my case called _cityReader.</p>
  
  <p>Now, if you set the _cityReader variable to a new instance of the Reader then call dispose on it (I also set it to null) then move the file (moving works fine) then call delete on the file's new location you will get an UnauthorizedAccessException on the delete operation...</p>
  
  <pre><code>_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");
  </code></pre>
  
  <p>What I've found is that if I use reflection to call Dispose the _cityReader._stream.Value property then in this scenario before calling dispose on the _cityReader variable itself then the file will delete...</p>
  
  <pre><code>_cityReader = new Reader(@"C:\temp\MaxMind\Active\GeoLite2-City.mmdb", FileAccessMode.MemoryMapped);
  
  FieldInfo field = typeof(Reader).GetField("_stream", BindingFlags.NonPublic | BindingFlags.Instance);
  ThreadLocal&lt;Stream&gt; fieldValue = (ThreadLocal&lt;Stream&gt;)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");
  </code></pre>
  
  <p>But, on top of this, I actually dispose of the static reader object on a different thread to the one it was created on and find that even doing this bit with reflection under that scenario means I still get the UnauthorizedAccessException.  In this scenario I find that I need to force a garbage collection after disposing of the _cityReader variable and setting it to null.  To reproduce this one, I have a static method in the console app like this...</p>
  
  <pre><code>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");
  }
  </code></pre>
  
  <p>Then in the main method of the console app I have this...</p>
  
  <pre><code>_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();
  </code></pre>
  
  <p>So that code sample will work, but if I remove the GC.Collect() call from the DisposeReaderAndSwitchFiles method I get the UnauthorizedAccessException.</p>
  
  <p>Has anybody else experienced similar issues with the MaxMind.Db.Reader object?</p>
  
  <p>Is there something I am doing wrong or something else I should be doing?  It feels a bit dirty forcing a garbage collection and I would rather avoid it if possible.</p>
  
  <p>Thanks,</p>
  
  <p>Phil</p>