.NET 4.0 и страшный OnUserPreferenceChanged Hang - PullRequest
11 голосов
/ 02 ноября 2010

Я страдаю от страшного OnUserPreferenceChanged Hang, на который довольно неплохо ссылается Иван Кривяков, здесь:

http://ikriv.com/en/prog/info/dotnet/MysteriousHang.html#BeginInvokeDance

Я недавно отправил вопрос, когда впервые столкнулся с проблемой:

Еще один вопрос отладки тупика в C #

Я думал, что решил эту проблему, удалив элемент управления, созданный из потока пользовательского интерфейса, но через некоторое время он снова появился (вероятно, никогда не ушел ...).

Мы использовали .NET 3.5, который, как я понимаю, использует CLR 2.0. Недавно приложение было обновлено для использования .NET 4.0 Client Profile / CLR 4.0. Кроме того, мы обновили с версии Infragistics WinForms 10.1 до 10.3. Единственное другое отличие состоит в том, что предыдущая версия была запутана ... кто-нибудь испытывал проблемы с запутыванием и зависанием?

У меня была еще одна попытка избавиться от зависаний любого приложения раз и навсегда, но необычно, я не смог воспроизвести зависание в самой последней версии (используя .NET 4.0). Зависание просто воспроизвести в предыдущей версии (с использованием .NET 3.5), используя удобное приложение Freezer Ивана Кривякова (см. Его статью), которое по запросу запускает сообщение WM_SETTINGCHANGE.

Может быть, я немного надеюсь, что проблема исчезла сама по себе, но кто-нибудь знает, были ли какие-либо изменения в CLR от 2.0 до 4.0, которые могли бы вызвать это?

-------------------------------------------- ---------РЕШЕНИЕ---------------------------------------- ----------

Таким образом, после тестирования вариантов приложения, например, CLR 2.0 + Infragistics 2010.1, CLR 2.0 + Infragistics 2010.3 и CLR 4.0 + Infragistics 2010.1, мы считаем, что мы выявили проблему, связанную с компонентом Infragistics в WinForms 2010.1 (без исправлений). Нам все еще предстоит воспроизвести стоп-кадр, используя CLR 2.0 или CLR 4.0 с Infragistics 2010.3, вместо этого (и мы довольно неплохо воспроизвели это сейчас ...).

Ответы [ 3 ]

15 голосов
/ 02 ноября 2010

Элемент управления, созданный из потока пользовательского интерфейса ...

Да, это хороший способ вызвать эту проблему. Основная проблема вызвана классом SystemEvents, у которого незавидная задача - вызывать события в нужном потоке. Событие UserPreferenceChanged является типичным источником проблем, многие элементы управления подписываются на него, чтобы они могли перекрашивать себя, когда пользователь меняет тему рабочего стола. Поставщик компонентов не будет упускать из виду необходимость этого. Кроме того, стандартные элементы управления .NET Framework в наборе инструментов.

Обычно приличный способ проверить эту проблему - заблокировать рабочую станцию ​​(нажать клавиши Win + L), а также способ, которым тупик обычно вызывается на компьютере пользователя. Переключение на защищенный рабочий стол имеет тенденцию вызывать событие. С дополнительными причудами это никогда не случается, когда вы отлаживаете свою программу, и что она имеет сложное поведение, связанное со временем, так как это имеет место, когда никто не находится на машине. Сложно отлаживать.

Один из стандартных способов попасть в такую ​​проблему - это проблема инициализации в программе. Самое первое событие SystemEvents, которое подписано, приводит к тому, что класс SystemEvents инициализирует себя и настраивает соединение, необходимое для получения этих уведомлений и создания соответствующего события. Пользовательский экран-заставка, который делает слишком много (т. Е. Больше, чем просто отображает растровое изображение) и работает в рабочем потоке, помеченном как STA, достаточно, чтобы сделать это неправильно. Что-то простое, как ProgressBar уже достаточно. SystemEvents предполагает, что рабочий поток является основным потоком программы и теперь может легко генерировать события в неправильном потоке в будущем. Есть одна хорошая диагностика для этого, если этот рабочий поток больше не существует, тогда генерируется исключение первого шанса. Вы можете увидеть это в окне вывода.

Или вы создаете другой поток пользовательского интерфейса и имеете формы в обоих потоках. Неизбежно, что одна из этих форм всегда будет получать событие не в том потоке.

Единственный достойный совет - признать, что создание пользовательского интерфейса в рабочем потоке - это ракетостроение, которое Microsoft также не знала, как это сделать правильно. Следует отметить, что элементы управления .NET 1.x имеют обработчик событий, который все еще работает правильно, когда он вызывается из неправильного потока, он просто вызывает Control.Invalidate (). Но это было знание, которое, похоже, было потеряно в 2.0, ToolStrip - хороший пример . И не верьте поставщику компонентов, чтобы получить это право, в частности, у Infragistics нет звездной репутации. Не делай этого.

2 голосов
/ 23 мая 2014

Лучшее руководство, которое я нашел для решения этой проблемы, здесь:

Он проведет вас через использование WinDbg для проверки причины ошибки и покажет, как найти причину ошибки. Как вы упомянули, скорее всего, это вызвано тем, что элемент управления создается в потоке без пользовательского интерфейса.

В моем случае я решил проблему, создав фабрику, которая использует SynchronizationContext из потока пользовательского интерфейса для создания элемента управления, а затем я вызываю CreateControl () для принудительного создания дескриптора пользовательского интерфейса.

Статья службы поддержки Microsoft находится здесь:

0 голосов
/ 01 июля 2015

Если вы запустите пример приложения с его веб-страницы с первым CLR 2.0, а затем с CLR 4.0, то вы заметите, что проблема, похоже, действительно исчезла в 4.0 - понятия не имею, что изменилось, но, возможно, они действительно решили проблему.BR

...