Te application I'm developing needs to dynamically create RadMap controls, and then dispose them after they are no longer required. The map typically has several layers (both InformationLayer and VisualizationLayer types). The ItemsSource property of each layer is typically bound to an observable collection. Some background threads are responsible for getting data and adding to the appropriate layer's observable collection (invoking onto the dispatcher thread if required). This approach all works well most of the time but occasionally when the RadMap is disposed we get an exception which crashes the application:
Telerik.Windows.Controls.DataVisualization : System.NullReferenceException
Object reference not set to an instance of an object.
at Telerik.Windows.Controls.Map.MapShapeData.SetLogicalWidth(Int32 zoomLevel)
at Telerik.Windows.Controls.Map.MapShapeData.CalculateScreenGeometry(Int32 zoomLevel, Boolean raisePropertyChanged)
at Telerik.Windows.Controls.Map.ShapeCoordinatesProcessor.StartProcessing(Object paramObject)
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()
The stack trace shows that it's happening on a background thread (i.e. not the thread I'm calling dispose on) and does not reference any of my code. Unfortunately I've not yet been able to replicate this in a simpler application but I'm hoping you may be able to suggest what I am doing wrong - is there a particular approach I need to take when disposing the map? I've tried various things, including stopping my background processing threads before disposal but so far I've not been able to fix the problem. The fact that the problem happens intermittently might suggest that there is a timing issue.
Can you suggest anything I should try?
Thanks
Pete
11 Answers, 1 is accepted
We have logged an issue observable when switching the layers of RadMap. You can check it on our public portal. Please, review the item and let me know if the scenario is different than the described one.
If the case is the same, a possible workaround for this issue is to use the VisualizationLayer.Visibility property for hiding unused layers instead of removing them from the RadMap Items collection.
Hope this is helpful.
Regards,
Tanya
Telerik by Progress
Hi Tanya,
Unfortunately there's not much information shown in your public portal for that issue, although from the brief description it doesn't sound quite the same.
Setting the layer visibility is for us not a solution to the problem. We specifically need to be able to display multiple different maps, each having layers displaying different items.In order to do this we need to be able to create RadMap controls in code, then dispose of those controls when they are no longer required. The exception we see seems to happen after the RadMap control is disposed (on a thread not under my control).
Thanks,
Pete
Another approach you can try is to clear up the source of the visualization layer before RadMap.
If this is still not helpful, I would like to ask you to share a sample project illustrating the issue so we can test it locally. Are you starting additional threads from the application?
Please, note that the public forums allow only images as an attachment. If you would like, you can submit a support ticket through your account. The support tickets are private and allow you attach archives as well.
Regards,
Tanya
Telerik by Progress
I've created a small project that enables replication of the problem. Build and run, then use the buttons at the top of the windows to add a few map controls then delete them. When I do this a few times I invariably cause an exception as described in my first post. In order to attach the sample I've renamed the zip file as png.
Thanks
Pete
Thank you for this isolation. This appears to be the same issue as the one in the portal Tanya mentioned. We updated its description to better illustrate the possible scenarios. Basically the Visualization Layer is removed from the Map in a moment when background threads process MapShapeData objects' geometries and this leads to the exception.
As a workaround in your scenario we would suggest removing the Layer's Items before Disposing the Map:
public
void
Dispose()
{
(
this
.RadMap.Items[0]
as
VisualizationLayer).Items.Clear();
RadMap.Dispose();
}
Please let us know if this fits well in your business case.
Regards,
Petar Mladenov
Telerik by Progress
Hi Petar,
I tried your suggested fix in the sample app I attached to my last post. Unfortunately it didn't work. Is there any other workaround you can suggest?
I notice the the issue in your portal was raised in 2014 - are you able to provide any update on when it may be fixed?
Thanks
Pete
This seems strange because we applied the fix to your project and it worked. Please check the attached video of a test in your app. You can also check the attached test project with R1 2017 trial binaries.
On a side, note we cannot currently provide an estimated time frame for a fix. You can follow the item in the portal in order to receive future change status notifications by email.
Regards,
Petar Mladenov
Telerik by Progress
Hi Petar,
Sorry for the delayed response (unfortunately I've been working on something else).
I tried the exact same test as you've shown in your video (with the compiled binaries from the test.rar file attached to your post) and I still saw the problem I described. Could this be due to difference (possibly timing related?) between my PC and yours?
My understanding is that there must be some background thread running (launched by the Telerik code). If the background thread executes after dispose is called then possibly the MapControl property of the layer is null which results in the exceptions.
Do you have any other suggestions? Is there any way for me to be sure that background processing has completed before I dispose the map control?
As I've explained, I'm using VisualizationLayer. Is there an alternative implementation using InformationLayer that might avoid this problem?
This issue is really causing us some pain now and we really need to find fix or workaround.
Thanks
Pete
Hi Petar,
Please see my post from yesterday. Here's a bit more information: the problem happens very infrequently but I'm still convinced it happens under some circumstances. Are there any circumstances which you can envisage it would happen? Obviously I need to make our application as robust as possible. If there are any other suggestions you can make in terms of changing how we dispose, using different layer type etc. that would be very helpful.
Thanks,
Pete
The Dispose method of VisualizationLayer starts with stopping the internal background threads. We think we have found an issue in the Dispose of RadMap - it fails to call the Dispose of child VisualizationLayers.
Could you please try the following workaround and if it works for you, we will make sure to fix the Dispose of RadMap for R2 ServicePack in June ?
In MapControl.xaml.cs:
public
void
Dispose()
{
(
this
.RadMap.Items[0]
as
VisualizationLayer).Dispose();
RadMap.Dispose();
}
Regards,
Petar Mladenov
Telerik by Progress
Hi Petar,
I'm glad you could find a potential explanation for the crash. I've implemented your suggested workaround and we haven't seen the issue since, so I'm hopeful it's fixed. As you suggest, it would be useful to include this in your June release.
Thanks
Pete