ThinkGeo.com    |     Documentation    |     Premium Support

FileBitmapTileCache with multiple MapControl instances

Hi Guys,


So we have multiple instance of map controls open in our WPF app and need to delete tiles at various times using a FileBitmapTileCache (we are using a WMSTileOverlay in the mapcontrol to request tiles from a WMSServer). I am getting file access errors right now when i delete tiles for a given bounding box and I assume this is because i have multiple instances of map controls, each with a  separate instance of a FileBitmapTileCache pointed at the same tile cache on disk. So it seems like the solution would be each for map control to use the same FileBitmapTileCache instance - am i on the right track in thinking this?


 


Thanks,


Chris



Unfortunately this approach doesn’t seem to help. I am still getting this error - 
  
 The process cannot access the file ‘C:\ProgramData\Roadnet Technologies\Roadnet Transportation Suite\TileCache\101\DEFAULT\4505.85777284337\3260744\3246604.png’ because it is being used by another process. 
  
 when running this code - 
  
                         FileBitmapTileCache fileBitmapTileCache = 
                             wmsOverlay.TileCache as FileBitmapTileCache; 
  
                         foreach (IMappable mapItem in mappableItems) 
                         { 
                             BaseShape shapeToClear = null; 
                             if (mapItem is IMappablePoint) 
                             { 
                                 shapeToClear = 
                                     ThinkGeoConversion.PointShapeFromCoordinate( 
                                         ((IMappablePoint)mapItem).Coordinate); 
                             } 
                             else if (mapItem is IMappablePath) 
                             { 
                                 shapeToClear = 
                                     ThinkGeoConversion.LineShapeFromCoordinates( 
                                         ((IMappablePath)mapItem).Coordinates); 
                             } 
  
                             Collection<BitmapTile> tiles = 
                                 fileBitmapTileCache.GetTiles(shapeToClear.GetBoundingBox()); 
  
                             foreach (BitmapTile tile in tiles) 
                             { 
                                 fileBitmapTileCache.DeleteTile(tile); 
                             }

 Christopher, I am not suprised you are getting an error when attempting the second approach.  As you have already found out, having multiple map instances share the same FileBitmapTileCache would cause file access conflicts.  I have not yet tried this but it sounds like your first approach should work if each FileBitmapTileCache points to a seperate directory. But again, I see too much RAM usage here.


This is an interesting problem which will be tricky, even for ThinkGeo to solve.   But, they have a bag full of tricks.



Yup it’s too bad though because of the memory and in our case it makes sense as a singleton. Digging around a little more this code is similar to what Howard had recommended in the past and i’m not getting the file access error but it still doesn’t seem to be deleting the tiles. 
  
                             // Get cells in the specified extent. 
                             Collection<TileMatrixCell> intersectingCells =  
                                 fileBitmapTileCache.TileMatrix.GetIntersectingCells( 
                                     shapeToClear.GetBoundingBox()); 
  
                             // Create a tile cache object with the cache directory and cache id. 
                             FileBitmapTileCache fileBitmapTileCacheWDeleteAccess = new FileBitmapTileCache( 
                                 fileBitmapTileCache.CacheDirectory,  
                                 fileBitmapTileCache.CacheId); 
                             fileBitmapTileCacheWDeleteAccess.TileAccessMode = TileAccessMode.ReadAddDelete; 
  
                             foreach (ZoomLevel zoomLevel in Map.ZoomLevelSet.GetZoomLevels()) 
                             { 
                                 double scale = zoomLevel.Scale; 
                                 fileBitmapTileCacheWDeleteAccess.TileMatrix.Scale = scale; 
                                 foreach (TileMatrixCell cell in intersectingCells) 
                                 { 
                                     // create a bitmap whoes size equals to the tile size. 
                                     BitmapTile tile = new BitmapTile(cell.BoundingBox, scale); 
                                     fileBitmapTileCacheWDeleteAccess.DeleteTile(tile); 
                                 } 
                             } 
  


Actually, although it may be I just haven’t tested it enough, it seems like using a single tile cache with multiple map control instances works ok as far as displaying the tiles. If there was just a way to get the cache to momentarily release it’s locks on the files so that they could be deleted as needed and then updated with a Map.Refresh() call it seems like it could be made to work. 
  
 For a little background: We are using a WMS Server but have map editing built in to our system so that the rendering engine on the server will actually pick up user specific map edits - but in order for this to work we need to be able to clear out and refresh the tiles covering those edits on the client.

Good investigation and thanks for sharing.  Sounds like there is a thread resource contention issue in multiple tile mode.

Christopher, 



Thanks for your investigation about that. I think we don't have a good function to force delete locked image file, you can create try to delete it after other process release it. I think a background service could help you asynchronous delete.

  

Regards, 



Don