ThinkGeo.com    |     Documentation    |     Premium Support

Map Threading Fix

I am not sure where to go from here but I have downloaded the newest update for the Desktop Edition and have set the threading model to SingleThreading and I am still getting exceptions.  I am doing as Microsoft recommends for threading in that I raise an event and the map winforms object is subscribed to that event.  Worked fine in 2.0 and still works fine in 2.0 but does not work in 3.0.


I am now getting the following exception:


at System.Drawing.Pen.get_PenType()

   at System.Drawing.Pen.get_Brush()

   at ThinkGeo.MapSuite.Core.GdiPlusGeoCanvas.x80259444712de393()

   at ThinkGeo.MapSuite.Core.GdiPlusGeoCanvas.FlushCore()

   at ThinkGeo.MapSuite.Core.GeoCanvas.Flush()

   at ThinkGeo.MapSuite.DesktopEdition.LayerOverlay.xa6cb874f7090c07f(GeoCanvas x31c084515ae9393f)

   at ThinkGeo.MapSuite.DesktopEdition.LayerOverlay.DrawCore(GeoCanvas canvas)

   at ThinkGeo.MapSuite.DesktopEdition.Overlay.Draw(GeoCanvas canvas)

   at ThinkGeo.MapSuite.DesktopEdition.xf0380b1a0bc40ca6.StartDraw()

   at ThinkGeo.MapSuite.DesktopEdition.x601a5561df898600.StartDraw(Int32 tileWidth, Int32 tileHeight, RectangleShape tileExtent, Collection`1 overlays)

   at ThinkGeo.MapSuite.DesktopEdition.x601a5561df898600.RefreshDynamic(Collection`1 overlays)

   at ThinkGeo.MapSuite.DesktopEdition.x65fdca92d79c01f5.RefreshDynamic()

   at ThinkGeo.MapSuite.DesktopEdition.WinformsMap.RefreshDynamic()

   at EPIC.Works.LiveMap.asset_PositionAdded(Object sender, AssetPositionAddedEventArgs e) in C:\Users\Curtis\Documents\Visual Studio 2008\Projects\EPIC Works 3\EPIC Works\LiveMap.cs:line 191

   at EPIC.Works.BusinessObject.AbstractAsset.OnPositionAdded(AssetPositionAddedEventArgs e) in C:\Users\Curtis\Documents\Visual Studio 2008\Projects\EPIC Works 3\EPIC Works\BusinessObject\AbstractAsset.cs:line 175

   at EPIC.Works.BusinessObject.MobileAsset.AddPosition(Position position) in C:\Users\Curtis\Documents\Visual Studio 2008\Projects\EPIC Works 3\EPIC Works\BusinessObject\MobileAsset.cs:line 56

   at EPIC.Works.BusinessObject.MobileAsset.liveUpdate_DoWork(Object sender, DoWorkEventArgs e) in C:\Users\Curtis\Documents\Visual Studio 2008\Projects\EPIC Works 3\EPIC Works\BusinessObject\MobileAsset.cs:line 75


I have also included the two methods which appear to be causing the issue.  I have alot of the code commented in the one in an attempt to isolate the issue.


Any ideas?


Thanks.


Curtis


 


PositionAdded



private void asset_PositionAdded(object sender, AssetPositionAddedEventArgs e) {
GeoPen pen = new GeoPen(new GeoSolidBrush(GeoColor.StandardColors.Blue));
pen.SetLineCap(DrawingLineCap.Round, DrawingLineCap.Round, GeoDashCap.Round);
pen.Width = 6;
//Hashtable synchronizedAssetLines = Hashtable.Synchronized(assetLines);

//if (enableTruckTrack) {
//    InMemoryFeatureLayer truckTrackLayer = (InMemoryFeatureLayer)Map.FindFeatureLayer(e.Position.Asset.AssetId.ToString() + "|Track");
//    if (truckTrackLayer == null) {
//        LineShape lineShape = new LineShape();
//        lineShape.Vertices.Add(new Vertex(e.Position.convertToDecimalDegrees(e.Position.Longitude), e.Position.convertToDecimalDegrees(e.Position.Latitude)));
//        synchronizedAssetLines.Add(e.Position.Asset.AssetId.ToString(), lineShape);

//        truckTrackLayer = new InMemoryFeatureLayer();
//        truckTrackLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = new LineStyle(pen);
//        truckTrackLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
//        Map.DynamicOverlay.Layers.Add(e.Position.Asset.AssetId.ToString() + "|Track", truckTrackLayer);
//    } else {
//        // If the hashtable contains the asset then we need to generate the layer and remove the asset from the hashtable.
//        if (synchronizedAssetLines.ContainsKey(e.Position.Asset.AssetId.ToString())) {
//            LineShape lineShape = (LineShape)synchronizedAssetLines[e.Position.Asset.AssetId.ToString()];
//            synchronizedAssetLines.Remove(e.Position.Asset.AssetId.ToString());

//            lineShape.Vertices.Add(new Vertex(e.Position.convertToDecimalDegrees(e.Position.Longitude), e.Position.convertToDecimalDegrees(e.Position.Latitude)));
//            truckTrackLayer.InternalFeatures.Add("Track", new ThinkGeo.MapSuite.Core.Feature(lineShape));
//        } else {
//            LineShape lineShape = (LineShape)truckTrackLayer.InternalFeatures["Track"].GetShape();
//            lineShape.Vertices.Add(new Vertex(e.Position.convertToDecimalDegrees(e.Position.Longitude), e.Position.convertToDecimalDegrees(e.Position.Latitude)));
//            truckTrackLayer.InternalFeatures["Track"] = new ThinkGeo.MapSuite.Core.Feature(lineShape);
//        }
//    }
//}

DrawTruck(e.Position);
Map.RefreshDynamic();
}

DrawTruck



private void DrawTruck(EPIC.Works.BusinessObject.Position position) {
InMemoryFeatureLayer truckLayer = null;

Dictionary<String, String> dictionary = new Dictionary<String, String>();
dictionary.Add("LAT", position.convertToDecimalDegrees(position.Latitude).ToString());
dictionary.Add("LONG", position.convertToDecimalDegrees(position.Longitude).ToString());
dictionary.Add("SPEED", "18mph");
dictionary.Add("HEADING", position.Heading.Trim());
dictionary.Add("NAME", position.Asset.AssetDescription);

if(Map.FindFeatureLayer(position.Asset.AssetId.ToString()) == null){
truckLayer = new InMemoryFeatureLayer();
truckLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle.PointType = PointType.Bitmap;
truckLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle.Image = new GeoImage("C:\\dumptruck.png");
//truckLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.CreateMaskTextStyle("[NAME]\nHeading: [HEADING]\nSpeed: [SPEED]", "Arial", 8, DrawingFontStyles.Bold, GeoColor.StandardColors.Black, GeoColor.StandardColors.Black, 2, -34, -30);
truckLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
truckLayer.InternalFeatures.Add("Truck", new ThinkGeo.MapSuite.Core.Feature(new PointShape(Convert.ToDouble(dictionary["LONG"]), Convert.ToDouble(dictionary["LAT"])), dictionary));

Map.DynamicOverlay.Layers.Add(position.Asset.AssetId.ToString(), truckLayer);
} else {
truckLayer = (InMemoryFeatureLayer)Map.FindFeatureLayer(position.Asset.AssetId.ToString());
PointShape pointShape = new PointShape(Convert.ToDouble(dictionary["LONG"]), Convert.ToDouble(dictionary["LAT"]));
pointShape.Id = "Truck";

truckLayer.Open();
truckLayer.EditTools.BeginTransaction();
truckLayer.EditTools.Update(pointShape, dictionary);
truckLayer.EditTools.CommitTransaction();
truckLayer.Close();
}
}


The exception is System.InvalidOperationException: Object is currently in use elsewhere. 
  
 Thanks. 
 Curtis

Bump, any ideas what might be causing this?  Is this the same threading issue we have been seeing with the Beta?


Thanks.


Curtis



Curtis, 
  
   Sorry for not getting to this sooner.  We are a bit behind on posts but will catch up.  I have seen this error before and it is typically when a GDI+ object is being used in two places at once.  I think that even though you are raising the event that the refresh is happening on your thread.  How often is the event being raised to draw the truck?  Could you try to put some code in before you refresh the truck like below.  This will at least prevent your own refreshing getting in each others way.  This still would not solve the issue if you did a refresh and then at the same time you were panning or zooming in and we were drawing. 
  
   I think that even if the map is in single threaded mode it doesn’t stop you the user from spawning multiple threads and calling into our objects from them.  The good new is that in a very near version we will have some guidelines for multi threading with our control. 
  
 lock(map) 
 { 
 Draw the truck 
 } 
  
 Can you elaborate a little more on the method you are using?  From what I remember when you interact with a Winforms object from another thread you need to do a method invoke on it to make sure the call is happing on the UI thread.  Any information you could provide would be helpful. 
  
 Thanks you very much for your post because it brings up another dimension to the issue.  I will work to re-create this and get back with you as soon as possible. 
  
 David