I’ve run into another problem with the Desktop Map. It appears that once I load a shape file layer, the underlying shape file remains locked until the process exits. My current project requires me to load and unload shape files, including copying them around, renaming them, moving them, and possibly deleting them. Obviously this presents a major problem.
I’ve attached a repro that shows the problem. If you run it, you will see 3 buttons and a map. If you click Test before Load, you will see a success message. Clicking Load results in seeing a shape file load in the map with a bunch of points. Click Test now shows an error message about locked shape files. Clicking Unload runs the code that I thought should, well, “unload” the shape files. It basically just clears the overlay layer and refreshes the map. Is there something more I need to do to get the map code to unlock the shape files?
In summary, my goal is to have “Test” successfully rename the files after having previously clicked “Load”.
ShapeFileLocking.zip (46.4 KB)
Shape files remain locked forever once loaded
I don’t think it should be necessary, but I found that the following code set just before the Layers.Clear works to unlock the files. Is this somehow correct? Or is this just a work around. It seems to me that if the layers are not in use, they should not be keeping files locked. In fact, if I call Layers.Clear first, then all references to layers will be lost with no hope of closing.
foreach( Layer layer in staticLayerOverlay.Layers )
{
if ( layer.IsOpen )
layer.Close( );
}
Hi Russ,
It’s necessary for us to call the layer.close() method before rename the Shapefile. The reason is that when we call the layer.Open() method the file will be lock even through we don’t use it in the code after until the layer.close() method is called, but it’s unnecessary to clear the layers before rename the files just close the layers which need to be renamed. The code maybe like the following:
private string[] GetAllShapeFiles( )
{
foreach (Layer layer in staticLayerOverlay.Layers)
{
if (layer.IsOpen)
layer.Close();
}
string shapeFilePath = Path.Combine( Application.StartupPath, “ShapeFiles” );
string[] files = Directory.GetFiles( shapeFilePath, “*.shp” );
Debug.Assert( files.Length > 0 );
return files;
}
Thanks,
Peter
Thank you. But I don’t need to modify/delete/rename the files while displayed, only afterward.
But I still believe this is a bug. The layers were never explicitly opened in my code. They were read once to draw the map, which opened them to do so. So if the map opened them and was done with them, it should close them. If not immediately, then I would at least expect it to close them when the map/overlay is cleared. In code I write, I make it a point to close all such resources IMMEDIATELY after accessing data, and never leave file handles and such locked any longer that absolutely necessary.
And here is the deal closer. Once the layer has been cleared, if you didn’t save a reference, the files that I didn’t write code to load/lock will remain locked forever. In my opinion, that point alone puts this squarely in bug territory…
Obviously I eventually figured out how to work around this by explicitly closing. But it was not at all expected and wasted a bit of time. Long enough for me to create a reduced case and post the question here.
Hi Russ,
Thanks for you information here. In the desktop edition user don’t need to open the layers explicitly before map refresh, it will be done internally, to consider the performance the layers don’t be closed, because almost all the operations on the map will trigger the refresh, such as Zoom In/Out, Pan, etc. if we open and close the layers frequently, I think it will run into the performance issue.
The reason why the layers don’t be closed when the map/overlay is cleared is that the map/overlay is cleared means that the layers aren’t displayed in the map but it can’t indicate if the layers don’t be used somewhere else, it will be caused other issue if close the layers which are cleared from the map/overlay.
For your requirement we can binding the events ClearedItems or ClearingItems for map.Overlays or overlay.Layers.
Thanks,
Peter