2011-02-16 44 views
3

在開發WPF/WinForms互操作應用程序時,我遇到了一個討厭的問題。我一直試圖解決這個問題三天,但我無法取得任何進展。我懷疑我可以提供足夠的信息來獲得解決方案,但我正在尋找任何能夠解釋這裏究竟發生了什麼的人?System.Windows.Forms中的AccessViolationException,在WPF中使用WinFormsHost

我正在使用的組件是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,MSG的Int32,IntPtr的wParam中,IntPtr的LPARAM) 在System.Windows.Forms.NativeWindow.DefWndProc(消息&米) 在System.Windows.Forms的.Control.DefWndProc(消息&米) 在System.Windows.Forms.AxHost.WndProc(消息&米) 在System.Windows.Forms.Control.ControlNativeWindow.OnMessage(消息&米) 在System.Windows.Forms的.Control.ControlNativeWindow.WndProc(Message & m) at 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

ProcMon screenshot

這一觀點已被過濾,以顯示該類型的唯一結果,但似乎這種情況正是兩次,每個DLL。這是否意味着什麼?

現在,很明顯我對所發生的事情以及如何解決這個問題毫無頭緒。如果你有線索,你可以善意向我解釋我正在處理的問題是什麼類型的?

任何想法如何調試此問題?

回答

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事件時,使用新的表面大小重新初始化底層的地圖控件,這似乎可靠地在地圖完全繪製爲適當的大小之前發生,並保持布爾mapIsInitialized字段在我的WPF控件中保持爲false,直到地圖初始化爲非零表面大小,設置適當的投影,並且地圖第一次被完全繪製。除了mapIsInitialized之外,我現在訪問底層地圖控件的函數(例如將屏幕轉換爲經緯度)將不會執行任何操作。

所以,你可能會也可能不會有類似的問題,但我會嘗試跟蹤初始化代碼,並查看傳遞給底層映射控件的參數的值,看看它們是否有意義,如果初始化按照您的預期發生,則在適當的時候使用適當的值。

祝你好運!

相關問題