AccessViolationException из System.Windows.Forms, используя WinFormsHost в WPF

Я столкнулся с неприятной проблемой при разработке приложения взаимодействия WPF/WinForms. Я пытался решить эту проблему в течение трех дней, но я не могу добиться успеха. Я сомневаюсь, что могу предоставить достаточно информации, чтобы получить решение, но я ищу кого-нибудь, кто мог бы объяснить, что здесь происходит?

Компонент, который я использую, - это AxMapControl (ESRI ArcGIS Engine 9.3.1 SP2), который, насколько мне известно, представляет собой встроенный в COM код, представленный как элемент управления WinForms. Компонент встроен в наше клиентское программное обеспечение WPF (.NET 3.5) с использованием WPF WinFormsHost proxy.

Периодически приложение сильно падает с AccessViolationException, Это всегда происходит в ответ на щелчок мышью пользователя на элементе управления картой, но, похоже, нет какой-либо рифмы или причины того, что именно вводится. Трассировка стека всегда одинакова:

System.AccessViolationException: попытка чтения или записи в защищенную память. Это часто указывает на то, что другая память повреждена. в System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam) в System.Windows.Forms.NativeWindow.DefWndProc(Message& m) в System.WrolFor. (Сообщение & m) в System.Windows.Forms.AxHost.WndProc(Сообщение & m) в System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Сообщение & m) в System.Windows.Forms.Control.ControlNativeWindow.WndProc(Сообщение & m) в System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Поскольку исключение, похоже, выбрасывается за пределы любого стека вызовов, инициированного моим кодом, я не могу понять, как перехватить исключение и обработать его программно.

Эта проблема возникает в режиме отладки, а также в сборках выпуска. Однако это происходит не на всех компьютерах, но я смог повторить эту проблему на Windows 7 и XP, а также.NET Framework 3.5 и 4.0.

При проверке того, что происходит во время аварии, выясняется, что аномалия CreateFileMapping операции над библиотеками, развернутыми GAC, которые приводят к ошибке FILE LOCKED WITH ONLY READERS,

Скриншот ProcMon

Это представление было отфильтровано, чтобы показать только результаты этого типа, но, похоже, это происходит ровно дважды с каждой DLL. Это что-то значит?

Теперь очевидно, что я не знаю, что происходит и как решить эту проблему. Если у вас есть подсказка, не могли бы вы быть добрыми и объяснить мне, с каким типом проблемы я имею дело?

Любая идея, как я мог отладить эту проблему?

1 ответ

Я использую другой элемент управления картой, отличный от ESRI, но мои настройки очень похожи: собственный код карты, обернутый в COM, обернутый в элемент управления Windows Forms, а затем перенесенный в приложение WPF через WindowsFormsHost. И несколько недель назад я получил точно такое же исключение System. AccessViolationException, когда щелкнул карту, и у меня было очень мало вариантов для отладки.

Виновник в моей проблеме: инициализация базового элемента управления в WPF происходит не так, как я думал - WPF откладывает определенную инициализацию до тех пор, пока представление не станет полностью необходимым / видимым на экране (я предполагаю сократить время загрузки окна / элемента управления), В WPF я помещал весь свой код инициализации для базового элемента управления картой в конструктор и обработчик событий (WPF) UserControl.Loaded. Проблема заключалась в том, что WPF вызывает конструктор и вызывает событие Loaded до того, как все действительно станет видимым на экране. Таким образом, мой базовый элемент управления картой был инициализирован с размером поверхности 0 высота, 0 ширина, что является допустимым, но не правильным. Когда я нажимал на карту, я вызывал базовый элемент управления карты, чтобы преобразовать мой щелчок мыши (x, y) в широту, и это вызвало исключение AccessViolationException.

Мое исправление состояло в том, чтобы повторно инициализировать базовый элемент управления картой с новым размером поверхности всякий раз, когда возникает событие UserControl.Resize, которое, по-видимому, надежно происходит непосредственно перед тем, как карта полностью отрисовывается в ее правильном размере, и сохранять поле bool mapIsInitialized в моем WPF управление, которое остается ложным до тех пор, пока карта не будет инициализирована с ненулевым размером поверхности, настроены правильные проекции и карта полностью раскрашена в первый раз. И мои функции (например, преобразование точек экрана в широты), обращающиеся к базовому элементу управления картой, теперь ничего не делают, если только mapIsInitialized.

Таким образом, у вас может возникнуть или не возникнуть аналогичная проблема, но я постараюсь обойти код инициализации и посмотреть на значения аргументов, которые передаются в базовый элемент управления map, чтобы увидеть, имеют ли они смысл и имеет ли место инициализация. происходит, как вы ожидаете, с правильными значениями в нужное время.

Удачи!

Другие вопросы по тегам