在开发WPF / WinForms互操作应用程序时,我遇到了一个令人讨厌的问题。我一直试图解决这个问题三天,但我无法取得任何进展。我怀疑我能提供足够的信息来获得解决方案,但我正在寻找任何能够解释究竟在这里发生什么的人?
我正在使用的组件是AxMapControl(ESRI ArcGIS Engine 9.3.1 SP2),据我所知,它是COM包装的本机代码,公开为WinForms控件。该组件使用WPF WinFormsHost代理嵌入在我们的WPF(.NET 3.5)客户端软件中。
应用程序会定期使用AccessViolationException
进行崩溃。这总是发生在用户鼠标点击地图控件时,但似乎没有任何押韵或原因在什么具体输入。堆栈跟踪始终相同:
System.AccessViolationException:尝试读取或写入受保护的内存。这通常表明其他内存已损坏。 在System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc,IntPtr hWnd,Int32 msg,IntPtr wParam,IntPtr lParam) 在System.Windows.Forms.NativeWindow.DefWndProc(消息& m) 在System.Windows.Forms.Control.DefWndProc(消息& m) 在System.Windows.Forms.AxHost.WndProc(消息& m) 在System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 在System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 在System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd,Int32 msg,IntPtr wparam,IntPtr lparam)
因为异常似乎抛出了我的代码启动的任何调用堆栈之外,我无法弄清楚如何捕获异常并以编程方式处理它。
此问题发生在调试模式以及发布版本中。但它确实不会出现在所有计算机上,但我能够在Windows 7和XP以及.NET framework 3.5和4.0上复制此问题。
检查崩溃发生时进程是什么,异常似乎是GAC部署的DLL上似乎有多个CreateFileMapping
操作失败,结果为FILE LOCKED WITH ONLY READERS
。
此视图已被过滤以仅显示该类型的结果,但似乎每个DLL恰好发生两次。这是什么意思吗?
现在,很明显我对发生的事情毫无头绪,以及如何解决这个问题。如果你有线索,你能否善待并向我解释我正在处理什么类型的问题?
知道如何调试此问题吗?
答案 0 :(得分:1)
我正在使用除ESRI之外的其他地图控件,但我的设置非常相似:用COM包装的本机地图代码,包装在Windows窗体控件中,然后通过WindowsFormsHost引入WPF应用程序。几个星期前,当我点击我的地图时,我得到了完全相同的System.AccessViolationException,只有很少的选项可以帮助调试。
我的问题的罪魁祸首:WPF中底层控件的初始化并没有像我想象的那样发生 - WPF推迟某些初始化,直到视图在屏幕上完全需要/可见(我假设减少窗口/控制加载时间)。在WPF中,我将基础地图控件的所有初始化代码放入构造函数和(WPF)UserControl.Loaded事件处理程序中。问题是,WPF调用构造函数并在事物在屏幕上真正可见之前引发Loaded事件。所以我的底层地图控件正在初始化,表面大小为0高度,0宽度,这是合法的但不正确。当我点击地图时,我正在调用底层地图控件,将我的鼠标单击(x,y)转换为lat long,并引发了AccessViolationException。
我的解决方法是每当引发UserControl.Resize事件时,使用新的表面大小重新初始化底层地图控件,这似乎可以在地图完全以适当的大小绘制之前可靠地发生,并保持bool mapIsInitialized字段在我的WPF控件中,在将地图初始化为非零曲面大小之前保持为假,设置了正确的投影,并且第一次完全绘制了地图。除非mapIsInitialized,否则我的函数(例如将屏幕点转换为lat lons)访问底层地图控件现在什么都不做。
所以,你可能有或没有类似的问题,但我会尝试跟踪初始化代码并查看传递给底层地图控件的参数的值,看看它们是否有意义,如果初始化正如您所期望的那样,在适当的时间使用适当的值。
祝你好运!