Диалог ожидания

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Диалог ожидания

Сообщение А.Н. » 26.03.2010 23:12:43

Когда выполняется долгая операция, пользователю неплохо показывать, что программа ещё не сдохла.
Пытался сделать диалог ожидания с анимацией. Форма, на форме, TImage.
Картинки загружаются из ImageList и меняются через определённый интервал.

Проблема в том, что обычный таймер, в windows, не идёт (что, собственно, понятно, т.к. сообщения не обрабатываются). Поэтому приходится мудрить. Использовать такое, как "мультимедийный" таймер не хочется.
Пробовал сделать таймер в отдельном потоке. Но, обновлять приходится через Synchronize, иначе он выдаёт
ошибки. Естественно, что всё замирает, пока не выполнится ожидаемое действие.
Пробовал создавать форму в новом потоке. Ради интереса. Ругается по-чёрному. :-\
Application.ProcessMessages, естественно, не катит, поскольку, действием может быть, например выполнение запроса:
Код: Выделить всё
ShowWaiter();
Query.Open();
HideWaiter();


Поискал, подумал. Ничего не нашёл, голова не работает. Да и лениво.
Может, кто-нибудь знает как сделать? И... Может даже поделится? :-)
А.Н.
постоялец
 
Сообщения: 230
Зарегистрирован: 13.03.2010 12:23:58

Re: Диалог ожидания

Сообщение Odyssey » 27.03.2010 11:51:00

Теоретически, надо бы делать Query.Open(); в отдельном потоке, т.е. писать наследника от TThread, внутри которого делать Query.Open(), а из основного потока запускать этот thread и по его завершении прятать диалог. Т.е. делать так,чтобы весь GUI оставался в основном потоке. К сожалению, проверенного, рабочего примера кода у меня нет, но тоже с удовольствием бы взглянул на такой пример.
Odyssey
энтузиаст
 
Сообщения: 580
Зарегистрирован: 29.11.2007 17:32:24

Re: Диалог ожидания

Сообщение Timid » 27.03.2010 12:34:46

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

Примеров множество. Поищите компонент работы с потоками TThread, но лучше всего идти на delphikingdom.info и почитать там.
Timid
постоялец
 
Сообщения: 290
Зарегистрирован: 21.11.2007 21:33:15

Re: Диалог ожидания

Сообщение А.Н. » 27.03.2010 13:13:37

Да я понимаю, что нужно выполнять работу в отдельном потоке. По-идее, это правильно.
Но не знаю как будет Query, если результаты выводятся в DBGrid (поиск). Ведь, по-идее, он будет обновлять грид из другого потока без Synchronize... Но не знаю тут.
Дело-то в том, что у меня не расчёт. Именно выполнение запросов. Не знаю имеет ли особый смысл его останавливать... Сейчас всё, естественно, делается в единственном потоке, который и за GUI отвечает.
В принципе, меня это устраивает. Поэтому неплохо просто вынести форму в отдельный поток, например.
Даже просто - ради интереса. Ведь в другом процессе всё будет работать?
Как вариант - сделать отдельное приложение, выводящее диалог ожидания. Вариант очень некрасивый.
Не вариант. По-идее, неплохо просто обновлять форму, например, вызывая её метод, который использует
блокировку на время обновления.
Процесс, по крайней мере в виндавс, - просто контейнер потоков..? Т.е. в принципе, нет большой разницы, между потоком в текущем процессе и потоком в новом процессе?

Добавлено спустя 3 минуты 43 секунды:
А "Королевство" я знаю. Может, на delphi я бы ещё и написал такое... Не знаю.
Помнится я как-то тоже серьёзно накосячил с синхронизацией.
Но на Lazarus, вообще, как-то многое не так...

Чего ему мешает? Может, создать ещё один объект класса TApplication? o.O
Дикие мысли какие-то... Лучше никому не рассказывать. :-D
А.Н.
постоялец
 
Сообщения: 230
Зарегистрирован: 13.03.2010 12:23:58

Re: Диалог ожидания

Сообщение AbakAngelSoft » 28.03.2010 13:44:26

Timid писал(а):delphikingdom.info
О! И как давно королевство перебралось на info? У меня в закладках ru, а раньше по моему был com. Проверил работаю все три варианта. :0

А.Н. писал(а):Ведь в другом процессе всё будет работать?

В другом потоке нет.
VCL в делфи и соответственно LCL в лазаре заточены под то что бы работать в одном потоке который считается основным потоком. Используется много глобальных переменных и т.д. Т.е. чтобы вынести форму в отдельный поток надо переписать весь LCL и часть FCL, а оно того не стоит.

А.Н. писал(а):Но на Lazarus, вообще, как-то многое не так...

Меня удивляет что наооборот в Lazarus почти все так-же, свой компилятор, сбои библиотеки, кросплатформенность в конце концов. Но вместо юниксового Fork испльзуется тот-же TThread! Это супер круто!

А.Н. писал(а):Может, создать ещё один объект класса TApplication?

Не поможет, глобальную переменную Application подменить только для одной формы все равно не получится.
Аватара пользователя
AbakAngelSoft
постоялец
 
Сообщения: 273
Зарегистрирован: 06.08.2008 19:28:26
Откуда: Краснодар

Re: Диалог ожидания

Сообщение Timid » 29.03.2010 08:32:26

AbakAngelSoft писал(а):Меня удивляет что наооборот в Lazarus почти все так-же, свой компилятор, сбои библиотеки, кросплатформенность в конце концов. Но вместо юниксового Fork испльзуется тот-же TThread! Это супер круто!

Форк в Windows потребует сделать обертку через критические секции, что-то придумать с памятью переменных и т.д. А объект - он все в себе держит :)


А.Н. писал(а):Но не знаю как будет Query, если результаты выводятся в DBGrid (поиск). Ведь, по-идее, он будет обновлять грид из другого потока без Synchronize... Но не знаю тут.
Дело-то в том, что у меня не расчёт. Именно выполнение запросов. Не знаю имеет ли особый смысл его останавливать... Сейчас всё, естественно, делается в единственном потоке, который и за GUI отвечает.
В принципе, меня это устраивает. Поэтому неплохо просто вынести форму в отдельный поток, например.
Даже просто - ради интереса. Ведь в другом процессе всё будет работать?
Как вариант - сделать отдельное приложение, выводящее диалог ожидания. Вариант очень некрасивый.
Не вариант. По-идее, неплохо просто обновлять форму, например, вызывая её метод, который использует
блокировку на время обновления.


Я понимаю, что буду выглядеть немного извращенцем, но я вообще не использую никакие гриды кроме DrawGrid.
А данные для него храню как динамический массив из записей (по структуре полей запроса).

Это развязывает мне руки - заполняю массив когда хочу (хоть из потока, хоть асинхронно), могу использовать критические секции, для обновления грида использую таймер (раз в 5 сек - оптимально).
onDrawCell - для вывода данных из массива в грид.
Timid
постоялец
 
Сообщения: 290
Зарегистрирован: 21.11.2007 21:33:15

Re: Диалог ожидания

Сообщение Climber » 29.03.2010 09:32:44

А.Н. писал(а):Да я понимаю, что нужно выполнять работу в отдельном потоке. По-идее, это правильно.
Но не знаю как будет Query, если результаты выводятся в DBGrid (поиск). Ведь, по-идее, он будет обновлять грид из другого потока без Synchronize... Но не знаю тут.
Может, так?
Код: Выделить всё
DBGrid.DataSource:=nil;
Query.Open;
DBGrid.DataSource:=MyDataSource;
Тогда, открывая датасет в отдельном потоке, мы никак не влияем на грид, который обрабатывается в основном. А когда данные уже загружены, подключаем грид обратно. Кстати, можно отключение/подключение в основном потоке сделать.
Climber
постоялец
 
Сообщения: 415
Зарегистрирован: 03.06.2007 20:09:57
Откуда: Москва

Re: Диалог ожидания

Сообщение dunin » 29.03.2010 10:04:12

Climber писал(а):Может, так?
Код: Выделить всё
DBGrid.DataSource:=nil;
Query.Open;
DBGrid.DataSource:=MyDataSource;
Тогда, открывая датасет в отдельном потоке

Код: Выделить всё
DBGrid.DataSource:=nil;
Query.Open; // <------ и где тут отдельный поток?
DBGrid.DataSource:=MyDataSource;
Аватара пользователя
dunin
энтузиаст
 
Сообщения: 634
Зарегистрирован: 02.05.2007 13:18:11
Откуда: Тољя††и

Re: Диалог ожидания

Сообщение Climber » 29.03.2010 11:59:31

dunin писал(а):Query.Open; // <------ и где тут отдельный поток?

А это домашнее задание :mrgreen: Как отвязать грид от датасета, открыть датасет и привязать обратно в отдельном потоке :roll: Я только идею предложил...
Climber
постоялец
 
Сообщения: 415
Зарегистрирован: 03.06.2007 20:09:57
Откуда: Москва

Re: Диалог ожидания

Сообщение А.Н. » 29.03.2010 12:37:48

AbakAngelSoft писал(а):сбои библиотеки

Хорошая опечатка. ;)

кросплатформенность в конце концов.

Вот это, действительно, очень здорово. Причём, какая кроссплатформенность. Хорошо сделано.

Но вместо юниксового Fork испльзуется тот-же TThread! Это супер круто!

А что такого? Зачем делать fork()? Ведь, в любом случае, TThread - обёртка над API..?
А раз уж заявлена совместимость с Delphi... Кстати, тоже немаловажно. Хотя, совместимость и неполная, но,
как самодостаточная среда, Lazarus очень неплох. Особенно, учитывая то, что он бесплатный...

Не поможет, глобальную переменную Application подменить только для одной формы все равно не получится.

Не факт... Возможно, перед вызовом диалога, подменять Application, производить обновление в критической секции, затем снова его подменять на оригинальный... Хм... Мда, изврат. :(

Timid писал(а):Я понимаю, что буду выглядеть немного извращенцем, но я вообще не использую никакие гриды кроме DrawGrid.

Я так понимаю, что у вас, на базе DrawGrid, уже нехилая библиотечка самостоятельно написанных компонентов? ;)

Это развязывает мне руки - заполняю массив когда хочу (хоть из потока, хоть асинхронно), могу использовать критические секции, для обновления грида использую таймер (раз в 5 сек - оптимально).
onDrawCell - для вывода данных из массива в грид.

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

Climber писал(а):Тогда, открывая датасет в отдельном потоке, мы никак не влияем на грид, который обрабатывается в основном. А когда данные уже загружены, подключаем грид обратно. Кстати, можно отключение/подключение в основном потоке сделать.

Уф, точно. Ведь ещё DisableControls есть. Да, я не подумал.
Эх, переписывать какие-то мрачноватые перспективы.... :(
А.Н.
постоялец
 
Сообщения: 230
Зарегистрирован: 13.03.2010 12:23:58

Re: Диалог ожидания

Сообщение AbakAngelSoft » 29.03.2010 12:49:32

А.Н. писал(а):А что такого? Зачем делать fork()? Ведь, в любом случае, TThread - обёртка над API..?

Я именно про это и говорю. Очень удобно писать код не задумываясь на какой платформе он будет работать, а занимаясь только своей работой. Написал потомка TThread и в windows и в linux с точки зрения программы он будет себя вести одинаково.
Аватара пользователя
AbakAngelSoft
постоялец
 
Сообщения: 273
Зарегистрирован: 06.08.2008 19:28:26
Откуда: Краснодар


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 34

Рейтинг@Mail.ru