Окно зависает, если в ListView есть много записей, добавленных из потоков - PullRequest
1 голос
/ 16 марта 2011

Моя программа выполняет «тяжелую» задачу (поиск файлов и поиск подписи) в отдельном потоке. Каждая задача использует PostMessage для вызова процедуры добавления записи в ListView.

Проблема в том, что когда ListView (часто) отображает много записей, мое окно зависает. Кажется, моя программа кричит, чтобы запросить Application.ProcessMessages. Только Progressbar все еще движется. После окончания операции все возвращается в норму.

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

Есть идеи?

Ответы [ 3 ]

8 голосов
/ 16 марта 2011

Однажды мы достигли предела того, сколько сообщений может быть отправлено в очередь сообщений. Скорее всего, вы также достигли этого предела.

С MSDN

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

С Лучшая синхронизация - без синхронизации

Проблема с PostMessage для основного потока графического интерфейса заключается в том, что вы можете «насыщать» основной насос сообщений GUI, и мешать WM_TIMER и Сообщения WM_PAINT (эти сообщения отправляется только если очередь сообщений пусто, а PostMessage означает, что очередь никогда не может быть пустой. В Кроме того, существует номинальный предел 10000 сообщений во входной очереди; после этого PostMessage откажется сообщение и вернуть ЛОЖЬ. В Кроме того, даже если ограничение в 10000 не ударил даже несколько сотен сообщений может означать, что пользователь видит плохое ответ на ввод с клавиатуры и мыши, недопустимая ситуация.

2 голосов
/ 16 марта 2011

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

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

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

0 голосов
/ 17 марта 2011

Вам следует рассмотреть возможность использования виртуального элемента управления сеткой, такого как ExGridView от Романа Мочалова, или очень популярного Virtual Tree View Майка Лишке (Delphi Gems). Когда поступает новое содержимое, просто установите флаг, а затем решите, как часто вы хотите обновлять экран, и обновлять асинхронно, но не один раз для каждого нового элемента, который появляется.

В любом случае, все пользователи смогут увидеть одно обновление на 200 мсек.

...