RhinoDoc finalizer throws AccessViolationException during unit tests

What I’m trying to acheive, is to verify that my custom export function is actually doing what it is supposed to be doing. This export function takes a subset of the geometry in a 3dm file, does some black magic to it, adds the results to a headless RhinoDoc and finally writes it to a 3dm file.

The code seems to be working fine, but once I run it in a unit test an System.AccessViolationException gets thrown somewhat randomly by the RhinoDoc finalizer. I observed this by decompiling the code. This crashes the unit test thread - but I can continue debugging and the code keeps running smoothly and does everything it is supposed to do - but because the unit test thread crashes and burns the test it self fails.

I’ve used this project as a baseline for my XUnit project:

Any thoughts on why this might be happening?

For some code context see the simplified and redacted code example:

[Theory]
[InlineData("TestModels\\SquareBox.3dm")]
public void TryExportGeometry(string filePath)
{
    var tempFolder = IOUtil.GetTempFolder();
    var extractionFilePath = Path.Combine(tempFolder, "extract.3dm");
    try
    {
        var doc = RhinoDoc.OpenHeadless(filePath);
        {
            var isExported = Export.TryExportGeometry(doc, extractionFilePath, isDebug: false);

            Assert.True(isExported);
            Assert.True(File.Exists(extractionFilePath));
            
            ... further testing
        }
    }
    finally
    {
        IOUtil.DeleteFolder(tempFolder);
    }
}

public static bool TryExportGeometry(RhinoDoc doc, string output3dmFilePath, bool isDebug)
{
   using (var extract = RhinoUtil.ExtractGeometry(doc)) 
   {
      ... analysis and manipulation of extracted geometry

      extract.Document.SaveAs(output3dmFilePath);
   }
}

public static GeometryExtractionResult ExtractGeometry(RhinoDoc doc)
{
    bool isSuccess = false;

    var tempFolder = IOUtil.GetTempFolder();

    RhinoDoc exportDoc = RhinoDoc.CreateHeadless(null);
    try
    {
        var docMetersPath = Path.Combine(tempFolder, $"{Guid.NewGuid()}.3dm");
        doc.SaveAs(docMetersPath);
        using (var docMeters = RhinoDoc.OpenHeadless(docMetersPath))
        {
            if (docMeters.GetUnitSystemName(true, true, true, true) != "m")
            {
                docMeters.AdjustModelUnitSystem(UnitSystem.Meters, scale: true);
                docMeters.Save();
            }

            var geometryIndex = docMeters.Layers.FindByFullPath(Paths.Geometry, notFoundReturnValue: -1);

            var geometryLayer = docMeters.Layers[geometryIndex];
            var geometryLayers = geometryLayer.GetChildren();

            var onlyMesh = docMeters.LayersOnlyContainRecursive(geometryLayers, ObjectType.Mesh);
            List<IGeometryInfo> exportedGeometry = new List<IGeometryInfo>();
            if (onlyMesh)
            {
                if (!TryExportAsMesh(doc, exportDoc, docMeters, geometryLayers, out var meshesInModel))
                    return null;

                exportedGeometry.AddRange(meshesInModel);
            }
            else
            {
                if (!TryExtractAsBreps(doc, exportDoc, docMeters, geometryLayers, out var brepsInModel))
                    return null;

                exportedGeometry.AddRange(brepsInModel);
            } 

            isSuccess = true; //Othewise it will be disposed
            return new GeometryExtractionResult(exportDoc, exportedGeometry);
        }
    }
    finally
    {
        IOUtil.DeleteFolder(tempFolder);
        if (!isSuccess)
            exportDoc?.Dispose();
    }
}

public class GeometryExtractionResult : IDisposable
{
    public RhinoDoc Document { get; set; }
    public IEnumerable<BrepInfo> BrepsInModel => Geometry.Where(x => x is BrepInfo).Select(x => x as BrepInfo);
    public IEnumerable<MeshInfo> MeshesInModel => Geometry.Where(x => x is MeshInfo).Select(x => x as MeshInfo);
    public List<IGeometryInfo> Geometry { get; private set; }

    public GeometryExtractionResult(RhinoDoc doc, IEnumerable<IGeometryInfo> geometry)
    {
        Document = doc;
        Geometry = new List<IGeometryInfo>(geometry);
    }

    public string CalcGeometryHash()
    {
        var sources = Geometry.GroupBy(x => x.SourceObjectId).Select(x => new { SourceObjectId = x.Key, SourceGeometry = x.First().SourceGeometry, LayerPath = x.Select(y => y.LayerPath).Distinct().Single() });
        if (!sources.Any())
            return null;

        return RhinoUtil.CalculateGeometryHash(sources.Select(x => (x.SourceGeometry, x.SourceObjectId, x.LayerPath)));
    }

    public void Dispose()
    {
        Document?.Dispose();
        foreach (var geometry in Geometry)
        {
            geometry?.Dispose();
        }
    }
}

public class BrepInfo : IGeometryInfo, IDisposable
{
    public readonly Brep Brep;
    public int LayerIndex { get; private set; }
    public string LayerPath { get; private set; }
    public Guid ObjectId { get; private set; }
    public Guid SourceObjectId { get; private set; }
    public GeometryBase SourceGeometry { get; private set; }
    public BrepInfo(Brep brep, GeometryBase sourceGeometry, int layerId, string layerPath, Guid objectId, Guid sourceObjectId)
    {
        this.Brep = brep.DuplicateBrep();
        this.LayerIndex = layerId;
        this.ObjectId = objectId;
        this.LayerPath = layerPath;
        this.SourceObjectId = sourceObjectId;
        this.SourceGeometry = sourceGeometry.Duplicate();
    }

    public void Dispose()
    {
        Brep?.Dispose();
        SourceGeometry?.Dispose();
    }
}