Как избежать мерцания в моем приложении?

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

То, что я делаю для каждого события из потока (может быть 100 событий за 1 миллисекунду), просто увеличивает глобальное целое число, чтобы подсчитать количество итераций. Затем я показываю этот номер в метке на главной форме. Как вы можете себе представить, быстрые обновления из потока приведут к тому, что это мерцание выйдет из-под контроля.

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

ПРИМЕЧАНИЕ. Я использую стили VCL, поэтому мерцание становится еще хуже.


person Jerry Dodge    schedule 29.01.2013    source источник
comment
Оконные статические элементы управления, TStaticText, не мерцают так, как это делает TLabel.   -  person David Heffernan    schedule 29.01.2013


Ответы (1)


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

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

ПРИМЕЧАНИЕ. Чем больше обновлений графического интерфейса вам нужно выполнить, тем выше может потребоваться настройка интервала таймера.

person Jerry Dodge    schedule 29.01.2013
comment
Проблема заключается не только в мерцании. Подумайте также, что бы пользователь получил от метки, которая, даже если плавно (без мерцания), показывала бы значение, изменяющееся 100000 раз в секунду. [+1] - person TLama; 29.01.2013
comment
Да, это также является частью проблемы, которая замедляет его, поэтому я упомянул в вопросе о том, что цель потока побеждает. - person Jerry Dodge; 29.01.2013