Найти, какой модуль блокирует поток пользовательского интерфейса - PullRequest
2 голосов
/ 02 ноября 2010

Это вопрос из двух частей:

  • Я работаю над большим проектом, в котором несколько плагинов, разработанных разными командами, загружаются в одну общую оболочку контейнера. Иногда я вижу, что мои обновления пользовательского интерфейса блокируются, поскольку существует несколько параллельных обновлений пользовательского интерфейса, и я хочу знать, есть ли способ узнать, какой компонент блокирует поток пользовательского интерфейса

  • В .net как мне создать отдельный поток пользовательского интерфейса, который требует интенсивной работы с пользовательским интерфейсом?

Много ценю вашу помощь. Спасибо.

Ответы [ 4 ]

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

Используйте отладчик.Debug + Break All, когда вы замечаете, что это блокирует.Затем Debug + Windows + Threads и выберите основной поток.Окно стека вызовов показывает вам, что он делает.

Угловой случай, когда эти плагины используют много вызовов Control.Begin / Invoke или Dispatcher.Begin / Invoke.В этом случае ваш поток пользовательского интерфейса не блокируется, он просто перегружен запросами на отправку целей делегата.И больше не может выполнять свои обычные обязанности, такие как перекраска окон и реагирование на события мыши и клавиатуры.С этим мало что можно сделать, кроме как работать с авторами плагинов, чтобы заставить их исправиться.

У вас уже есть поток пользовательского интерфейса, который создал первое окно.Создание дополнительных потоков, которые имеют свои собственные окна, возможно, но вызывает неразрешимые проблемы с Z-порядком окон (окно исчезнет под окном другого приложения) и щедрыми подсказками о потере многопоточности взаимодействия окон.

1 голос
/ 02 ноября 2010

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

Опция 1: Вместо использования push-модели (с помощью методов ISynchronizeInvoke) перейдите к модели pull (или poll), в которой пользовательский интерфейс запрашивает у плагина обновления. Это имеет следующие преимущества.

  • Это нарушает тесную связь между пользовательским интерфейсом и потоками работника / плагина, которые навязывает Control.Invoke.
  • Он возлагает ответственность за обновление потока пользовательского интерфейса на поток пользовательского интерфейса, к которому он все равно должен принадлежать.
  • Поток пользовательского интерфейса определяет, когда и как часто должно происходить обновление.
  • Нет риска переполнения насоса сообщений пользовательского интерфейса, как в случае с методами маршалинга, инициированными потоком рабочий / плагин.
  • Рабочий поток / плагин не должен ждать подтверждения того, что обновление было выполнено, прежде чем перейти к следующим шагам (т. Е. Вы получаете большую пропускную способность как для пользовательского интерфейса, так и для потоков рабочий / плагин).

Вариант 2: Плагин может принять экземпляр ISynchronizeInvoke вместо действительного Form или Control. Этот специальный объект синхронизации будет реализован с использованием выделенного потока и очереди, которая действует как буфер между плагином и пользовательским интерфейсом. Он будет принимать сообщения об обновлении с помощью обычных методов Invoke или BeginInvoke, что означает, что вы можете сохранить архитектуру и интерфейсы плагинов в основном нетронутыми, а затем перенаправлять эти сообщения в пользовательский интерфейс после некоторых типов операций фильтрации, слияния и регулирования произошло. Количество сообщений об обновлениях, существующих в синхронизирующем объекте, будет уменьшаться и возрастать по мере изменения рабочей нагрузки пользовательского интерфейса и плагинов. Он может быть достаточно умен, чтобы изменить стратегию пересылки при увеличении скорости сообщений.

1 голос
/ 02 ноября 2010

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

1 голос
/ 02 ноября 2010

Visual Studio 2010 (в более высоких SKU) включает в себя функции, чтобы проверить это. Если вы запустите свою программу под Concurrency Profiler, вы сможете точно определить, какие потоки ожидают какие блокировки, когда происходит взаимоблокировка. Кроме того, он выделит тупик (я верю в ярко-красный), чтобы его было легко найти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...