Select to view content in your preferred language

Threading Errors in ArcGISLocalDynamicMapServiceLayer

563
3
05-01-2013 08:55 AM
RonaldNatalie
Emerging Contributor
If I write a rather simple version that follows the example, these load into my map fine.

If I try to create these in a com control, I get an InvalidOperationException from the Dependency Object being invoked in the wrong thread.    Of course, it's way down in the bowels of the service diddling the Url:

> WindowsBase.dll!System.Windows.Threading.Dispatcher.VerifyAccess() + 0x4a bytes 
  WindowsBase.dll!System.Windows.DependencyObject.SetValue(System.Windows.DependencyProperty dp, object value) + 0x15 bytes 
  ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.ArcGISDynamicMapServiceLayer.Url.set(string value) + 0x2b bytes 
  ESRI.ArcGIS.Client.Local.dll!ESRI.ArcGIS.Client.Local.ArcGISLocalDynamicMapServiceLayer.CompleteServiceInitialize(ESRI.ArcGIS.Client.Local.LocalMapService service) + 0xba bytes 
  ESRI.ArcGIS.Client.Local.dll!ESRI.ArcGIS.Client.Local.LocalMapService.GetServiceAsyncInternal.AnonymousMethod__0(object s, System.ComponentModel.AsyncCompletedEventArgs e) + 0x4b bytes 
  ESRI.ArcGIS.Client.Local.dll!ESRI.ArcGIS.Client.Local.LocalService.OnStartCompleted() + 0x76 bytes 
  ESRI.ArcGIS.Client.Local.dll!ESRI.ArcGIS.Client.Local.LocalMapService.UpdateMapServicePropertiesCompleteStart.AnonymousMethod__c(ESRI.ArcGIS.Client.Local.LayersInfo layersInfo, ESRI.ArcGIS.Client.Local.Internal.RequestInfo requestInfo2) + 0x48b bytes 
  ESRI.ArcGIS.Client.Local.dll!ESRI.ArcGIS.Client.Local.Internal.Requests.ProcessResponse<ESRI.ArcGIS.Client.Local.LayersInfo>(string url, string queryParameters, System.Exception err, bool cancelled, string result, System.Action<ESRI.ArcGIS.Client.Local.LayersInfo,ESRI.ArcGIS.Client.Local.Internal.RequestInfo> callback) + 0x2d0 bytes 
  ESRI.ArcGIS.Client.Local.dll!ESRI.ArcGIS.Client.Local.Internal.Requests.Start<ESRI.ArcGIS.Client.Local.LayersInfo>.AnonymousMethod__3(object s, System.Net.DownloadStringCompletedEventArgs e) + 0x186 bytes 
  System.dll!System.Net.WebClient.OnDownloadStringCompleted(System.Net.DownloadStringCompletedEventArgs e) + 0x15 bytes 
  System.dll!System.Net.WebClient.DownloadStringOperationCompleted(object arg) + 0x2a bytes 
  mscorlib.dll!System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(object state) + 0x3e bytes 
  mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0xa7 bytes 
  mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0x16 bytes 
  mscorlib.dll!System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() + 0x60 bytes 
  mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch() + 0x149 bytes 
  mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() + 0x5 bytes 
  [Native to Managed Transition] 


I've tried routing the code that does all this to the same thread that the MainWindow (and the ArcGISRuntime.Initialize) is run in and it doesn't help.

Any ideas.
0 Kudos
3 Replies
MichaelBranscomb
Esri Frequent Contributor
Hi,

Can you zip up and post your example on this thread? (or email me on mbranscomb@esri.com)

Cheers

Mike
0 Kudos
RonaldNatalie
Emerging Contributor
Hi,

Can you zip up and post your example on this thread? (or email me on mbranscomb@esri.com)

Cheers

Mike


Actually, you can do this without any special code.

1.  Create a New ArcGISWpfApplication with the New Project in Visual Studio.
2.  Turn on one of the commented out map layers in the MainWindow.xaml
2.  Go to Applicacation.xaml and disable the initial load of the main window.
3.  From a thread other than the main thread create the MainWindow class (in my case it's a COM class).

The whole mainwindow will create properly but goes boom asynchronously early on with the path above.

Amusingly, I can work around this by kluging the service creation/start in my thread:

            map_pkg = new ArcGISLocalDynamicMapServiceLayer(map_file_name);
            //
            //  These next three lines are SUPPOSED to be handled automatically.
            //  However, this works around an internal bug in the ServiceLayer crash where it runs
            //  things in the wrong thread when we run out of a com context.
            //  It doesn't happen if we take care of starting up the service ourselves.
            // <KLUDGE>
            map_pkg.Service = new LocalMapService();
            map_pkg.Service.Path = map_file_name;
            map_pkg.Service.Start();
            // </KLUDGE>



I'll see if I can cut out the proprietary stuff and zip up a canned set of programs that does this later today.

Amusingly I've worked around this by forcing the service start in the right thread by inserting these lines before I return from the window creation...
0 Kudos
AaronHigh
Deactivated User
I'm having a very similar issue trying to access a LocalTiledLayer in a map that is created on its own thread. Is there a known workaround to prevent this issue? I've tried manually calling the .Initialize() method on the layer but it doesn't seem to have any effect.

   at System.Windows.Threading.Dispatcher.VerifyAccess()
   at System.Windows.DependencyObject.GetValue(DependencyProperty dp)
   at ESRI.ArcGIS.Client.Map.get_Layers()
   at ESRI.ArcGIS.Client.Map.getSpatialReferenceFromLayers()
   at ESRI.ArcGIS.Client.Map.get_SpatialReference()
   at ESRI.ArcGIS.Client.LayerCollection.<getTileLayerEnumerator>d__1.MoveNext()
   at ESRI.ArcGIS.Client.LayerCollection.get_HasTiledResources()
   at ESRI.ArcGIS.Client.LayerCollection.calculateLevelScheme(Boolean raiseInitialized)
   at ESRI.ArcGIS.Client.LayerCollection.layer_OnInitialized(Object sender, EventArgs args)
   at System.EventHandler`1.Invoke(Object sender, TEventArgs e)
   at ESRI.ArcGIS.Client.Layer.OnInitialized(EventArgs e)
   at ESRI.ArcGIS.Client.Layer.Initialize()
   at ESRI.ArcGIS.Client.TiledLayer.Initialize()
   at ESRI.ArcGIS.Client.ArcGISLocalTiledLayer.InitCompleted(Object sender, RunWorkerCompletedEventArgs e)
   at System.ComponentModel.BackgroundWorker.OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
   at System.ComponentModel.BackgroundWorker.AsyncOperationCompleted(Object arg)
   at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()


As an update: I'm able to instantiate the map and add the tiled layer if I invoke it to the UI thread, however the tiled layer is never initialized, even after a manual call to .Initialize()

someMap.Dispatcher.Invoke(delegate() {someMap.Layers.Add(tiledLayer); });
0 Kudos