Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

This is a problem I have been struggling with for awhile. The code below takes 1-3 input feature layers (pFLayer) that were stored into a list called pFeatureLayerCollection, casts them into IGeoDatasets and executes EucDistanceFull in parallel to get distance rasters from them. The output IGeoDatasets are added to a list. After the Parallel.ForEach ends, if there is more than 1 output raster, I attempt to get the localminimum of the rasters using the method below. It runs fine if I give it one input raster. It also runs fine if I run it with multiple rasters sequentially (not in parallel) However, if I try to execute it with more than one raster in parallel, it fails with this error every time: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. (Esri.ArcGIS.SpatialAnalyst at ESRI.ArcGIS.SpatialAnalyst.RasterLocalOpClass.LocalStatistics(IGeoDataset LocalData, esriGeoAnalysisStatisticsEnum Type)

             ESRI.ArcGIS.Geometry.IEnvelope pExt; //create a new envelope to hold the feature class' size information
            pExt = new EnvelopeClass(); //instantiate the envelope as an object
            pExt.XMin = **[Some given known double value]**;
            pExt.YMin = **[Some given known double value]**;
            pExt.XMax = **[Some given known double value]**;
            pExt.YMax = **[Some given known double value]**;

            string StrOutRasPath = **[Some given valid filepath]**;

            List<IGeoDataset> pMinimumGeodatasetCollection = new List<IGeoDataset>(); //store output distance rasters

            Parallel.ForEach(pFeatureLayerCollection, pFLayer =>
                ESRI.ArcGIS.DataSourcesRaster.IRasterWorkspace pTempRWS;
                ESRI.ArcGIS.Geodatabase.IGeoDataset pOutputRaster = null;
                ESRI.ArcGIS.GeoAnalyst.IRasterAnalysisEnvironment pEnv = null; //Create a raster analysis environment. This sets up an area to do raster operations in
                ESRI.ArcGIS.SpatialAnalyst.IDistanceOp pDistanceOP; //Create raster DistanceOp object
                pDistanceOP = new RasterDistanceOpClass(); //define the newly created object as a new raster distance operation object

                string g_tempFolder = null;
                lock (strOutRasPath) //threadsafe creation of folders from method
                    g_tempFolder = CreateTempFolder(strOutRasPath);

                lock (pWSF)
                    pTempRWS = (IRasterWorkspace)pWSF.OpenFromFile(g_tempFolder, 0);

                ESRI.ArcGIS.Geodatabase.IWorkspaceFactory pWSFact; //create general workspace factory (this is the directory you will be working in)
                //pWSFact = new ShapefileWorkspaceFactoryClass(); //set general workspace as a shapefile workspace. WARNING: USING THIS CAUSES A STRANGE COM REWRAPPING ERROR. IT IS AN ESRI BUG

                Type t = Type.GetTypeFromProgID("esriDataSourcesFile.ShapefileWorkspaceFactory"); //DO NOT REMOVE THIS LINE OR THE FOLLOWING TWO LINES. Fixes strange casting error from COM rewrapping. (ESRI BUGFIX)
                System.Object obj2 = Activator.CreateInstance(t);

                pWSFact = (ShapefileWorkspaceFactory)obj2;

                ESRI.ArcGIS.Geodatabase.IFeatureWorkspace pFeatureWorkspace; //create a feature workspace to handle features
                pFeatureWorkspace = (IFeatureWorkspace)pWSFact.OpenFromFile(g_tempFolder, 0); //set feature workspace as the shapefile workspace defined earlier, and specify a file location

                ESRI.ArcGIS.Geodatabase.IGeoDataset pTempMinRaster;             
                ESRI.ArcGIS.Geodatabase.IGeoDataset pTempGeodataset;
                ESRI.ArcGIS.Carto.IFeatureLayer pTempFeatureLayer;

                //Loop through all features.

                ESRI.ArcGIS.GeoAnalyst.IConversionOp pConvOp;
                pConvOp = new RasterConversionOpClass();

                ESRI.ArcGIS.Carto.IFeatureSelection pFeatureSelection;
                ESRI.ArcGIS.Geodatabase.ISelectionSet pSelectionSet;
                pSelectionSet = pFeatureSelection.SelectionSet; //Defines a selection set of features. The pFeatureLayer information is stored here.

                ESRI.ArcGIS.Geodatabase.IFeatureCursor pFCursor2;
                ESRI.ArcGIS.Geodatabase.IFeature pFeature2;
                ESRI.ArcGIS.Geodatabase.IQueryFilter pQueryFilter;

                pQueryFilter = new QueryFilterClass();
                pFCursor2 = pFLayer.Search(null, false);
                pSelectionSet = pFeatureSelection.SelectionSet;
                pFeature2 = pFCursor2.NextFeature();

                pEnv = (IRasterAnalysisEnvironment)pDistanceOP;
                pEnv.OutWorkspace = (IWorkspace)pTempRWS;
                pEnv.SetCellSize(esriRasterEnvSettingEnum.esriRasterEnvValue, cellsize);

                lock (pExt) //threadsafe grab of pExt from outside Parallel.Foreach
                    pEnv.SetExtent(esriRasterEnvSettingEnum.esriRasterEnvValue, pExt);

                    ESRI.ArcGIS.Geodatabase.IGeoDataset temporaryGeodataset = (IGeoDataset)pFLayer.FeatureClass;

                    pOutputRaster = pDistanceOP.EucDistanceFull(temporaryGeodataset, true, false, false);

                lock (pMinimumGeodatasetCollection) //threadsafe adding to the list of output geodatasets




            if (pMinimumGeodatasetCollection.Count == 1) //if just one input feature class
                pMinimumRaster = pMinimumGeodatasetCollection[0];
                pFeatureLayer = pFeatureLayerCollection[0];


            else if (pMinimumGeodatasetCollection.Count == 2) //if two input feature classes, get local minimum

                pMinimumRaster = LocalMinimum2Rasters(pMinimumGeodatasetCollection[0], pMinimumGeodatasetCollection[1], strOutRasPath + "\\tmpVoro0004");


There is the bulk of the code, and below is the implemented LocalMinimum method. LocalMinimum3Rasters does the exact same as LocalMinimum2Rasters, but acommodates for one more raster. The final line of this code is where the program is failing.

    public IGeoDataset LocalMinimum3Rasters(IGeoDataset pRaster1, IGeoDataset pRaster2, IGeoDataset pRaster3, string strOutPath)

        ESRI.ArcGIS.DataSourcesRaster.IRasterBandCollection pRBCollTmp;
        ESRI.ArcGIS.DataSourcesRaster.IRasterBand pRBand;

        ESRI.ArcGIS.DataSourcesRaster.IRasterBandCollection pRBColl;
        pRBColl = new RasterClass();
        pRBCollTmp = (IRasterBandCollection)pRaster1;
        pRBand = pRBCollTmp.Item(0);
        pRBCollTmp = (IRasterBandCollection)pRaster2;
        pRBand = pRBCollTmp.Item(0);
        pRBCollTmp = (IRasterBandCollection)pRaster3;
        pRBand = pRBCollTmp.Item(0);

        //Create a RasterLocalOp operator
        ESRI.ArcGIS.SpatialAnalyst.ILocalOp pLocalOp = new RasterLocalOpClass();

        ESRI.ArcGIS.Geodatabase.IWorkspace pWs;
        ESRI.ArcGIS.Geodatabase.IWorkspaceFactory pWSF = new RasterWorkspaceFactoryClass();
        pWs = pWSF.OpenFromFile(strOutPath, 0);

        return pLocalOp.LocalStatistics((IGeoDataset)pRBColl, esriGeoAnalysisStatisticsEnum.esriGeoAnalysisStatsMinimum);


What could be causing this error? It seems to be directly tied to parallelism - I've noted that all operations work perfectly fine if I use a regular foreach instead of Parallel.ForEach.

Extra information: The program creates the two distance rasters every time - If I go to the temporary folders I created in this code after the program crashes, I will find the two temporary rasters wholly intact and perfectly created.

share|improve this question
up vote 2 down vote accepted

I'd instantiate your raster workspace factory like you did with the shapefile workspace in the main loop this since it is also a singleton object:

//Create RasterWorkSpaceFactory
Type factoryType = Type.GetTypeFromProgID(
IWorkspaceFactory WSF = (IWorkspaceFactory)Activator.CreateInstance

It's also good practice to decrement the com objects while iterating. One place I see is with pFeature2. Before calling pFCursor2.NextFeature() on the cursor try calling:


I'm not sure if these two tips will directly fix your problem but should help memory management in your program and increase stability. I most often see the error you describe when trying to re-use an object that another method has diposed of. I don't have time to wrap my mind around you program but think about which objects are being re-used.

share|improve this answer
Thanks for your answer. I'll give these a shot. – Conor Jul 12 '13 at 18:36
Solved! Seems like the singleton object was the issue. I had several instantiations of RasterWorkspaceFactory strewn about my code that were instantiated using the "new" keyword. I got rid of all of these except for one instantiation and used CreateInstance instead of "new" and voila! My code now works without a crash. – Conor Jul 22 '13 at 19:45

I think your objects are crossing thread boundaries, which is a big no-no in ArcObjects.

See this help topic for more information.

share|improve this answer
I think you're right. I will give this a read-through. – Conor Jul 12 '13 at 18:53
The documentation you provided helped me get the answer. Thank you! – Conor Jul 22 '13 at 19:47

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.