Hi.
I'm experiencing an interesting exception in my application. Unfortunately I do not have the opportunity to make a sample to recreate the problem right now. I'm first off looking for an answer to what is really going on, and how to solve. Or at least brainstorm a little.
Rough outline: Graphics are published to a GraphicsProvider to add/update graphics in the maps. GraphicsObservers listen, and add to GraphicsOverlays. This way all maps using the same GraphicsProvider will contain the same synchronized data. My MapGraphic hold some properties for routing for which GraphicsOverlay it belongs to.
Graphics are batch-published to the provider, but the internal routing will result in individual add operations to the GraphicsOverlay. In previous versions of the API, there was an AddRange method available, but I chose not to use that at the time to reduce complexity as well as hoping that the performance lost through individual add was gained from not having to filter out the destinations for AddRange to work. In 100.4, the AddRange is not available.
I have started multiple tasks to retrieve and publish data to the provider. If I execute one task at the time (more or less), everything is ok most of the time. On the other hand, if I execute multiple simultaneous tasks, I get the exception below. For this scenario, the MapView, map, layers, etc have already been loaded and contains and display data. There is only one map observing the data. I have also experienced the same exception if I only have one task.
My suspicion is that the simultaneous tasks experience conflicts with each other, and that perhaps RuntimeCollection.ExecuteActionWithUndo is unable to handle the load for some reason? All the operations in RuntimeCollection use lock(this.SyncRoot), so this is a bit beyond my understanding.
In the past I have experienced similar oddities, and in those cases it turned out it was related to exceptions occuring inside of the Queue class and it not being thread safe. Replacing with ConcurrentQue fixed our issue then. Could it be a similar situation going on with RuntimeCollection? While I can't really see how, considering SyncRoot is in use for all updates.
System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: index
at Esri.ArcGISRuntime.RuntimeCollection`1.InsertItem(Int32 index, T item)
at Esri.ArcGISRuntime.RuntimeObservableCollection`1.InsertItem(Int32 index, T item)
at Shared.Map.MultiLayerGraphicsOverlayWrapper.Shared.Map.IGraphicsReceiver.OnAdd(MapGraphic graphic) in C:\Source\Shared.Map.Core\GroupLayer\MultiLayerGraphicsOverlayWrapper.cs:line 106
at Shared.Map.GroupLayerGraphicsObserver.AddToChildLayer(MapGraphic target, MapGraphic source) in C:\Source\Shared.Map.Core\GraphicsProviders\GroupLayerGraphicsObserver.cs:line 109
at Shared.Map.GroupLayerGraphicsObserver.OnPublish(MapGraphic source) in C:\Source\Shared.Map.Core\GraphicsProviders\GroupLayerGraphicsObserver.cs:line 78
at Shared.Map.GraphicsProvider.PublishInternal(MapGraphic graphic) in C:\Source\Shared.Map.Core\GraphicsProviders\GraphicsProvider.cs:line 62
at Shared.Map.GraphicsProvider.Publish(MapGraphic[] items) in C:\Source\Shared.Map.Core\GraphicsProviders\GraphicsProvider.cs:line 33
at Shared.Map.GraphicsProvider.Publish(IMapObject[] items) in C:\Source\Shared.Map.Core\GraphicsProviders\GraphicsProvider.cs:line 21
at Client.Resource.ResourceViewModel.<AddListInternal>z__OriginalMethod(IEnumerable`1 items) in C:\Source\Client\src\Resource\ResourceViewModel.cs:line 428
at Client.Resource.ResourceViewModel.<AddListInternal>c__Binding.Invoke(Object& instance, Arguments arguments, Object aspectArgs) in :line 16707564
at Client.Resource.ResourceViewModel.AddListInternal(IEnumerable`1 items) in :line 123
at Client.Resource.ResourceViewModel.InitializeFromServer(Int32[] districtIds) in C:\Source\Client\src\Resource\ResourceViewModel.cs:line 105
at Client.Resource.ResourceViewModel.Subscribed(Int32 districtId) in C:\Source\Client\src\Resource\ResourceViewModel.cs:line 127
at Client.District.DistrictViewModel.<>c__DisplayClass15_0.<UpdateNotifierSubscriptions>b__0() in C:\Source\Client\src\District\DistrictViewModel.cs:line 66
at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Client.District.DistrictViewModel.<UpdateNotifierSubscriptions>d__15.MoveNext() in C:\Source\Client\src\District\DistrictViewModel.cs:line 59
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Client.District.DistrictViewModel.<ToggleSelection>d__14.MoveNext() in C:\Source\Client\src\District\DistrictViewModel.cs:line 54
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Client.District.DistrictViewModel.<OnUpdateRouting>d__13.MoveNext() in C:\Source\Client\src\District\DistrictViewModel.cs:line 48
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)