NetTopologySuite / NetTopologySuite.IO.ShapeFile

The ShapeFile IO module for NTS.
35 stars 25 forks source link

Reader was disposed, cannot read from a disposed reader #27

Closed vishnu4 closed 4 years ago

vishnu4 commented 4 years ago

having an issue where i would like to read from a shape file, dispose the reader but hold the shape file information to do something with later. something like:

        private static IEnumerable<NetTopologySuite.IO.ShapeFile.Extended.Entities.IShapefileFeature> ProcessShapeFile(string shapeFilePath)
        {
            using (ShapeDataReader reader = new ShapeDataReader(shapeFilePath))
            {
                NetTopologySuite.Geometries.Envelope mbr = reader.ShapefileBounds;
                return reader.ReadByMBRFilter(mbr).ToList();
            }
        }

and then later, in another method that

var feats = ProcessShapeFile(path);
foreach (NetTopologySuite.IO.ShapeFile.Extended.Entities.IShapefileFeature f in feats)
                {
string clevelVal = f.Attributes["attName"];
...
}

on the attribute line, i get the following error:

_System.InvalidOperationException: Reader was disposed, cannot read from a disposed reader Stack Trace: DbaseReader.ReadEntry(Int32 index) <.ctor>b__1() Lazy1.CreateValue() Lazy1.LazyInitValue() Lazy`1.get_Value() IFeature.getAttributes()

is there any way to get what i'm looking for here, or can i not centralize the shape file loading/disposing like i'm hoping to?

DGuidi commented 4 years ago

replied in develop branch using this test

List<IShapefileFeature> data = null;
using (var reader = new ShapeDataReader("TestShapefiles/crustal_test.shp"))
{
    var mbr = reader.ShapefileBounds;
    data = reader.ReadByMBRFilter(mbr).ToList();
}
Assert.IsNotNull(data);
Assert.IsNotEmpty(data);

foreach (var item in data)
{
    Assert.IsNotNull(item.Geometry);
    Assert.IsNotNull(item.Attributes["ID_GTR"]);
}

Both asserts actually throws an InvalidOperationException in ShapeReader.ThrowIfDisposed method

DGuidi commented 4 years ago

@airbreather fix is straightforward, as long as it's acceptable to remove the Lazy objects that are the source of the error...

public ShapefileFeature(ShapeReader shapeReader, DbaseReader dbfReader, ShapeLocationInFileInfo shapeLocation, GeometryFactory geoFactory)
{
    FeatureId = shapeLocation.ShapeIndex;
    _lazyGeometry = new Lazy<Geometry>(() => shapeReader.ReadShapeAtOffset(shapeLocation.OffsetFromStartOfFile, geoFactory), LazyThreadSafetyMode.ExecutionAndPublication);
    _lazyAttributeTable = new Lazy<IAttributesTable>(() => dbfReader.ReadEntry(shapeLocation.ShapeIndex), LazyThreadSafetyMode.ExecutionAndPublication);

    // see https://github.com/NetTopologySuite/NetTopologySuite.IO.ShapeFile/issues/27
    var tempGeom = _lazyGeometry.Value;
    var tempAttrs = _lazyAttributeTable.Value;
}

see patch.zip simply as a suggestion.

DGuidi commented 4 years ago

@FObermaier @airbreather if you agree I can commit the code by myself

airbreather commented 4 years ago

as long as it's acceptable to remove the Lazy objects that are the source of the error

Sounds fine to me

DGuidi commented 4 years ago

please see PR #30