Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Программа и интерфейс
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 11.06.2015, 18:20
Аватар для SCrat.ORS
SCrat.ORS SCrat.ORS вне форума
Активный
 
Регистрация: 20.02.2007
Адрес: Мой адрес не дом и не улица, мой адрес 0x7С00
Сообщения: 208
Версия Delphi: 2006
Репутация: 884
По умолчанию Ошибка при частой Repaint

Есть главная форма, на ней ListBox в котором вручную (onDrawItem) отрисовываются итемы, используя какую-то информацию для заполнения.
Есть функция, назовём её RefreshInform, которая собирает эту информацию, и в конце запускает ListBox.repaint, чтобы onDrawItem нарисовал итемы.
При запуске главной формы, через отдельный юнит, запускается бесконечный поток, суть которого - через каждые 100 мс запускать Synchronize(MainForm.RefreshInform).
И вот тут меня ждала проблема. Через 5-10 минут работы, всё зависает и падает, а отладчик пишет "out of system resources" несколько раз, а затем "Stack overflow" и стек забит WM_PAINT.
Ну логично - забило, только вот почему? Сделал у функции RefreshInform некий глобальный флаг, который в начале устанавливается в False, а по окончанию в True, и, соответсвенно, в потоке перед вызовом RefreshInform стоит проверка этого флага. - Всё-равно падает.
Начал читать гугл, нашёл некую информацию, что repaint - виртуальный метод или что-то типа этого, мол используйте refresh он сделан для совместимости. Ок, сделал, запускаю - не помогло, такая же проблема. Читаю дальше, нахожу, что repaint и refresh делают принудительную перерисовку, а чтобы перерисовка была в порядке очереди, - используйте Invalidate, ок делаем так. Теперь проблема уменьшилась до одного сообщения "out of system resources", но так же всё зависает сначала, потом ошибка и всё падает.
Знаю что проблема именно в потоке из-за запуска функции RefreshInform в которой запускается выполнение перерисовки, - получается эдакая постоянная перерисовка. А если поставить условие, что например если в listbox изменился count, тогда запускать RefreshInform - все работает стабильно. Нужна помощь.
Суть всей этой балды, что бы в ListBox всегда была актуальная информация из-за постоянного обновления в потоке. Использовать банальное ListBox.String[i]:='Бла-бла-бла' - не получится, т.к. ListBox у меня является не более чем "контейнер" для строк, а содержимое строк рисуется из массива, поэтому реальные строки ListBox остаются пустыми, не содержат текста.
__________________
Програмистами не рождаются, ими становятся!

Последний раз редактировалось SCrat.ORS, 11.06.2015 в 18:41.
Ответить с цитированием
  #2  
Старый 11.06.2015, 19:05
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию

Зачем поток? Почему не обычный таймер?
__________________
— Как тебя понимать?
— Понимать меня не обязательно. Обязательно меня любить и кормить вовремя.


На Delphi, увы, больше не программирую.
Рекомендуемая литература по программированию
Ответить с цитированием
  #3  
Старый 11.06.2015, 19:48
Аватар для SCrat.ORS
SCrat.ORS SCrat.ORS вне форума
Активный
 
Регистрация: 20.02.2007
Адрес: Мой адрес не дом и не улица, мой адрес 0x7С00
Сообщения: 208
Версия Delphi: 2006
Репутация: 884
По умолчанию

Ну там такой фокус, что если количество итемов увеличелось, то выводится сообщение. Всё это нужно чтобы управление главной формой не останавливалось при показе сообщения. Да и таймер как-то слишком скучно, да и лишняя приблуда на форме.
__________________________________________
А вообще, ты прав. Суть ошибки заключается в том, что как-бы оно не было, поток кидает сообщение на перерисовку, а потом уже главная форма смотрит флаги и запускает перерисовку, но очередь сообщений из-за потока продолжает увеличиваться... Поэтому ставь флаги или не ставь, - сообщение от потока в очередь один хрен уходит, и по этому стек заполняется хочешь ты того или нет. И что бы вся эта шляпа заработала, единственный выход - это ставить на главную форму таймер, и посылать сообщения через него, причем в начале процедуры таймера - его выключать, после выполнения - включать, А поскольку сообщения кидает таймер - он зависит от главной формы, и в нём уже те самые флаги можно смотреть сразу, выставлять условие - посылать сообщение на перерисовку или нет... И всё стало работать.
__________________
Програмистами не рождаются, ими становятся!

Последний раз редактировалось SCrat.ORS, 11.06.2015 в 21:57.
Ответить с цитированием
  #4  
Старый 11.06.2015, 22:49
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,029
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Посмотри, можно ли переписать так, что бы обновление вызывалось только тогда, когда добавляется новый итем. Кстати, если форма с ListBox нормальная (т.е. созданная в нормальном потоке со ссылкой на Application), то при добавлении итема он сам перерисуется. Только делать это надо правильно. Добавлять итем надо из главного потока (VCL), вызывая соотв. код из вторичных потоков через Synchronize. Если у тебя несколько потоков добавляют итимы, то этот код надо вызывать в критической секции.
Ответить с цитированием
  #5  
Старый 12.06.2015, 15:19
Аватар для SCrat.ORS
SCrat.ORS SCrat.ORS вне форума
Активный
 
Регистрация: 20.02.2007
Адрес: Мой адрес не дом и не улица, мой адрес 0x7С00
Сообщения: 208
Версия Delphi: 2006
Репутация: 884
По умолчанию

С добавлением проблем как-раз нету, дело в том, что содержимое итема может меняться "из вне". Поэтому и стоит постоянная перерисовка.
__________________
Програмистами не рождаются, ими становятся!
Ответить с цитированием
  #6  
Старый 12.06.2015, 17:33
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

не нужно постоянно перерисовывать
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
  #7  
Старый 12.06.2015, 23:58
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,029
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Цитата:
Сообщение от SCrat.ORS
С добавлением проблем как-раз нету, дело в том, что содержимое итема может меняться "из вне". Поэтому и стоит постоянная перерисовка.

Ну, значит, перерисовывать только в случае изменения. Более того, еще в отрисовщике проверять - видим ли итем, который надо перерисовать.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра
Комбинированный вид Комбинированный вид

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 02:44.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter