Обработка сообщений Windows в заблокированной теме интерфейса? - PullRequest
2 голосов
/ 28 мая 2011

Возможно, это связано с обновлениями ProgressBar в заблокированном потоке пользовательского интерфейса , но немного по-другому.

При устранении неполадок в аварийном элементе управления WinForms (древовидный список DevExpress) член нашей команды столкнулся с необычной ситуацией, и мне интересно, сможет ли кто-нибудь помочь нам понять, что происходит. Английский не является его родным языком, поэтому я пишу от его имени.

Пожалуйста, посмотрите этот скриншот из Visual Studio 2005.

Обратите внимание на следующие моменты:

  1. Основной поток пользовательского интерфейса остановлен и в настоящее время использует метод отрисовки элемента управления DevExpress.

  2. Код, показанный на экране, взят из точки ранее в том же стеке вызовов. Этот код находится на уровне данных и был вызван в ответ на запрос элемента управления для отображения изображения для узла дерева. (возможно, также из обработчика Paint)

  3. Отображаемый код из более раннего в стеке вызовов, в главном потоке пользовательского интерфейса, и в настоящее время ожидает блокировки! Поскольку удаленные системы могут отправлять события, которые обрабатываются в фоновых потоках в модели данных (т. Е. Модели данных синхронизируются между клиентом и серверами), мы блокируем, чтобы обеспечить безопасность потока сбора данных.

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

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

Казалось бы, возможно, что это просто ошибка Visual Studio в представлении стека вызовов, за исключением того, что все это усилие является результатом попытки устранить неполадки случайного сбоя элемента управления в выпущенном приложении (в этом случае он показывает как большой красный X в пользовательском интерфейсе), поэтому кажется, что проблема не изолирована от среды отладки.

Хорошо, это было сложно, но, надеюсь, имело смысл. Есть идеи?

Ответы [ 3 ]

3 голосов
/ 28 мая 2011

Я бы настоятельно рекомендовал против блокировки пользовательского интерфейса, чтобы дождаться фоновой обработки.Рассмотрим что-то вроде множественная буферизация .Вероятно, вы можете довольно легко получить такое поведение, используя поточно-безопасные коллекции в .NET 4, но если это не вариант, есть версии в Parallel Extensions , выпущенных до v4.

0 голосов
/ 30 июня 2011

Мы видим нечто похожее в нашем проекте. Трассировка стека выглядит так, как будто цикл события насоса вызывается, пока поток пользовательского интерфейса ожидает блокировки. Это может произойти, если Monitor.enter имеет некоторые особые свойства при вызове в потоке пользовательского интерфейса. Я верю, что это то, что происходит, но я не нашел никакой документации, чтобы подтвердить это.

Возможно, это как-то связано с контекстами синхронизации:)

0 голосов
/ 28 мая 2011

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

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

Это не все исправляет, но, по крайней мере, уменьшает количество возможностей для взаимоблокировок.

...