Обработка сообщений происходит слишком медленно, что приводит к прерывистому, не отвечающему пользовательскому интерфейсу. Как мне использовать несколько потоков, чтобы облегчить это? - PullRequest
3 голосов
/ 23 апреля 2009

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

Могу ли я просто создать несколько потоков, считывая из одной очереди сообщений во всех из них и позволяя кому-либо из них обрабатывать каждое сообщение?

Если так, как это можно сделать?

Если нет, можете ли вы предложить другой способ решения этой проблемы?

Ответы [ 3 ]

13 голосов
/ 23 апреля 2009

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

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

4 голосов
/ 23 апреля 2009

Если бы это было позже, я бы сказал, используйте API-интерфейсы для асинхронных агентов (подключите для того, над чем я работаю) в , который еще не выпущен Visual Studio 2010 , однако, что я бы сказал, учитывая Сегодняшние инструменты - это разделение работы, в частности, в своем насосе для передачи сообщений вы хотите сделать как можно меньше работы, чтобы идентифицировать сообщение и передать его другому потоку, который будет обрабатывать работу (надеюсь, что нет информации о локальной потоке, которая требуется). Передача его другому потоку означает вставку его в потокобезопасную очередь какого-либо вида, либо заблокированную, либо без блокировки, а затем задает событие, которое другие потоки могут наблюдать, чтобы извлечь элементы из очереди (или просто извлечь их напрямую). Для большей эффективности вы можете использовать «очередь на кражу работы» с пулом потоков.

Это завершит получение работы из потока пользовательского интерфейса, чтобы поток пользовательского интерфейса мог выполнять дополнительную работу (например, рисование результатов этой работы), вам необходимо сгенерировать сообщение Windows, чтобы пробудить поток пользовательского интерфейса и проверить результаты, Самый простой способ сделать это - иметь другую очередь «готовых к работе» рабочих объектов для выполнения в потоке пользовательского интерфейса. представьте себе очередь, которая выглядит следующим образом: threadsafe_queue<function<void(void)> в основном вы можете проверить, является ли она непустой в потоке пользовательского интерфейса, и если есть рабочие элементы, то вы можете выполнить их встроенными. Вам нужно, чтобы рабочие объекты были как можно более короткими, и желательно, чтобы они вообще не блокировали .

Еще один метод, который может помочь, если вы все еще видите реакцию на резкое движение, - это либо убедиться, что обратный вызов потока не выполняется дольше 16 мс, и что вы не берете никаких блокировок или не выполняете какой-либо ввод-вывод. в потоке пользовательского интерфейса. Существует ряд инструментов, которые могут помочь идентифицировать эти операции, наиболее свободно доступным является 'инструментарий производительности Windows' .

0 голосов
/ 23 апреля 2009

Создайте отдельный поток при обработке длинной операции, т. Е. Сделайте ее проще, проблема в том, что какой-то код, который вы выполняете, занимает слишком много времени, это код, который должен иметь отдельный поток.

...