Select to view content in your preferred language

GroupLayer: Layer pointer should be locked before being accessed.

1115
4
Jump to solution
08-20-2013 12:22 PM
Labels (1)
BKuiper
Frequent Contributor
Hi,

I'm experiencing problems when trying to remove a GroupLayer from the Map. It keeps crashing on the NativeLayerPointer with the following error
"Layer pointer should be locked before being accessed." when trying to retrieve the pointer.

Is there a specific way how GroupLayers should be removed ?

How can i provide more debug information to Esri so this can be fixed or resolved? I'm not sure if I can provide a PoC.

Thank you

EDIT 2:
I think it is a threading issue when multiple layers are being added to the GroupLayer, which causes the _lockedOnThreadId, _lockCount to be out of sync, but this is a guess. I'm further investigating.

There should probably be a lock on the '_lockCount' integer.

EDIT 1: Call stack:
System.InvalidOperationException: Layer pointer should be locked before being accessed.
   at ESRI.ArcGIS.Client.Runtime.NativeLayerPointer.get_Ptr()
   at ESRI.ArcGIS.Client.Runtime.NativeLayerPointer.op_Implicit(NativeLayerPointer p)
   at ESRI.ArcGIS.Client.Runtime.NativeGroupLayer.RemoveLayer(Layer layer)
   at ESRI.ArcGIS.Client.Runtime.NativeGroupLayer.ClearChildLayers(IEnumerable`1 layers)
   at ESRI.ArcGIS.Client.Runtime.NativeGroupLayer.Dispose(Boolean disposing)
   at ESRI.ArcGIS.Client.Runtime.NativeLayer.Dispose()
   at ESRI.ArcGIS.Client.Runtime.NativeGroupLayer.Dispose()
   at ESRI.ArcGIS.Client.NativeMap.RemoveLayer(Layer layer)
   at ESRI.ArcGIS.Client.DrawingSurface.RemoveLayer(Layer layer)
   at ESRI.ArcGIS.Client.Map.RemoveMapLayer(Layer layer)
   at ESRI.ArcGIS.Client.Map.Layers_CollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
   at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
   at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
   at System.Collections.ObjectModel.Collection`1.Remove(T item)
   at XXX.LayerManagement.LayerManager.RemoveLayer(Layer layer) in XXX\LayerManager.cs:line 463
   at XXXViewModel.ExecuteRemoveLayerCmd(Object parameter) in XXXViewModel.cs:line 391
   at DelegateCommand.Execute(Object parameter) in DelegateCommand.cs:line 117
   at Telerik.Windows.Controls.RadMenuItem.ExecuteCommand() in c:\TB\117\WPF_Scrum\Release_WPF\Sources\Development\Controls\Navigation\Menu\RadMenuItem.cs:line 3202
   at Telerik.Windows.Controls.RadMenuItem.OnClickImpl() in c:\TB\117\WPF_Scrum\Release_WPF\Sources\Development\Controls\Navigation\Menu\RadMenuItem.cs:line 1686
   at Telerik.Windows.Controls.RadMenuItem.OnClick() in c:\TB\117\WPF_Scrum\Release_WPF\Sources\Development\Controls\Navigation\Menu\RadMenuItem.cs:line 2330
   at Telerik.Windows.Controls.RadMenuItem.ClickItem() in c:\TB\117\WPF_Scrum\Release_WPF\Sources\Development\Controls\Navigation\Menu\RadMenuItem.cs:line 3722
   at Telerik.Windows.Controls.RadMenuItem.HandleMouseUp() in c:\TB\117\WPF_Scrum\Release_WPF\Sources\Development\Controls\Navigation\Menu\RadMenuItem.cs:line 1667
   at Telerik.Windows.Controls.RadMenuItem.OnMouseLeftButtonUp(MouseButtonEventArgs e) in c:\TB\117\WPF_Scrum\Release_WPF\Sources\Development\Controls\Navigation\Menu\RadMenuItem.cs:line 1999
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
   at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
   at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
0 Kudos
1 Solution

Accepted Solutions
MichaelBranscomb
Esri Frequent Contributor
Hi,

Sorry about that - it's a known bug and has been addressed for the 10.2 release.

Cheers

Mike

View solution in original post

0 Kudos
4 Replies
MichaelBranscomb
Esri Frequent Contributor
Hi,

Sorry about that - it's a known bug and has been addressed for the 10.2 release.

Cheers

Mike
0 Kudos
MichaelBranscomb
Esri Frequent Contributor
... in the meantime there are a couple of workarounds:

#1. Lock the layer yourself while performing the layer removal:

private void RemoveAcceleratedLayer(ESRI.ArcGIS.Client.Layer layer)
{
    ESRI.ArcGIS.Client.GroupLayerBase container = Container(layer);
    if (container != null)
        RemoveAcceleratedLayer(layer, container);
    else
        MyMap.Layers.Remove(layer);
}

void RemoveAcceleratedLayer(ESRI.ArcGIS.Client.Layer layer, ESRI.ArcGIS.Client.GroupLayerBase gl)
{
    System.Type Tds = layer.GetType().Assembly.GetType("ESRI.ArcGIS.Client.DrawingSurface");
    var field = Tds.GetField("NativeLayerProperty", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
    var dependencyProperty = (DependencyProperty)field.GetValue(null);
    var nativelayer = layer.GetValue(dependencyProperty);
    var lockprop = nativelayer.GetType().GetProperty("Lock", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
    var lockobj = lockprop.GetValue(nativelayer, null);
    using (lockobj as System.IDisposable)
        gl.ChildLayers.Remove(layer);
}

ESRI.ArcGIS.Client.GroupLayerBase Container(ESRI.ArcGIS.Client.Layer layer)
{
    return AllLayers(MyMap.Layers).OfType<ESRI.ArcGIS.Client.GroupLayerBase>().FirstOrDefault(gl => gl.ChildLayers.Contains(layer));
}

System.Collections.Generic.IEnumerable<ESRI.ArcGIS.Client.Layer> AllLayers(System.Collections.Generic.IEnumerable<ESRI.ArcGIS.Client.Layer> layers)
{
    return layers.Concat(layers.OfType<ESRI.ArcGIS.Client.GroupLayerBase>().SelectMany(glb => AllLayers(glb.ChildLayers)));
}


#2. Register an unhandled exception handler, check the exception then flag it as handled.

Implement the handler and check:
private void HandleUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
       if ( e.Exception is TargetInvocationException &&
              e.Exception.InnerException is NullReferenceException &&
              e.Exception.InnerException.StackTrace.Contains("DrawingSurface"))
              e.Handled = true;
}


Register the handler (e.g. in the window constructor):
Application.Current.DispatcherUnhandledException += HandleUnhandledException;


Let me know if you have any trouble with these workarounds.

Cheers

Mike
0 Kudos
BKuiper
Frequent Contributor
Thanks, this fix works.
0 Kudos
BKuiper
Frequent Contributor
I can confirm that this is fixed in 10.2
0 Kudos