Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.07.18;
Скачать: CL | DM;

Вниз

что-то типа ShowModal, но иначе :)   Найти похожие ветки 

 
dUM ©   (2005-06-24 17:24) [0]

Пока в программе выполняются какие-то действия, пользователю нужно показать какое-нибуть окошко с прогресс баром, или просто с надписью вроде "ожидайте". Я делаю примерно вот так:

form1.Enabled:=false;
form2.show;
.....
.....
form2.close;
form2.Enabled:=true;

Но данный вариант мне очень не по душе. Подскажите, если ли альтернативы? Грубо говоря нужно чтобы во время отображения form2, у пользователя небыло доступа ни к каким функциям form1. Ну что-то типа SHowModal, только чтобы ещё и мой код паралельно выполнялся)


 
liver   (2005-06-24 17:26) [1]

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


 
Юрий Зотов ©   (2005-06-24 17:41) [2]

> dUM ©   (24.06.05 17:24)

Показываете форму с прогрессбаром модально, а код выполняете в отдельном потоке, вот и все проблемы. Стандартное, миллион раз проверенное решение.


 
jack128 ©   (2005-06-24 19:48) [3]

Не, я не люблю потоки постоянно делать.. Что то типа токого использую..
var
 WndList: Pointer;
 CancelForm: TCancelForm;
begin
 WndList := DisableTaskWindows(0);
 CancelForm := nil;
 try
   CancelForm := TCancelForm.Create(nil);
   CancelForm.Show;
   while (CancelForm.ModalResult = mrNone) and NeedDoWork do
     DoSamething;
 finally
   CancelForm.Free;
   EnableTaskWindows(WndList);
 end;
end;


 
dUM ©   (2005-06-24 21:43) [4]

Всем спасибо за идеи :)


 
uny ©   (2005-06-24 22:35) [5]

:) на окошке лучше написать "Пожалуйста ждите", "Please Wait", звучит лучше:)


 
Defunct ©   (2005-06-25 00:49) [6]

> jack128
try
  CancelForm := TCancelForm.Create(nil);
  ..
finally
  CancelForm.Free;
..

гм.. интересный код ;)


 
Поручик ©   (2005-06-25 11:16) [7]

F := TForm.Create(nil);
try
 F.FormStyle := fsStayOnTop;
 F.Show;
 while ... do
 begin
   ...
   F.Caption := "Обработано ХХХ%";
   F.Refresh;
   Appication.ProcessMessages;
   ...
 end;

finally
 F.Free;
end;


 
jack128 ©   (2005-06-25 12:31) [8]

Defunct ©   (25.06.05 0:49) [6]
гм.. интересный код ;)

код абсолютно коректен..
jack128 ©   (24.06.05 19:48) [3]
CancelForm := nil;
try


 
Defunct ©   (2005-06-25 14:17) [9]

> jack128

вот я и говорю. интересный код. ;)


 
Юрий Зотов ©   (2005-06-25 16:54) [10]

> jack128

Жень, а если эта самая DoSomething выполняется полчаса?


 
Defunct ©   (2005-06-25 17:25) [11]

> Юрий Зотов

Ну и пусть себе выполняется. А если поток полчаса выполняться надумал?

<off>
С прошедшим!
Желаю Вам всего того, что Вы сами себе пожелаете ;>
</off>


 
Юрий Зотов ©   (2005-06-25 17:31) [12]

> Defunct ©   (25.06.05 17:25) [11]

> А если поток полчаса выполняться надумал?

То форма спокойно продолжает получать и обрабатывать сообщения. Она нормально перерисовывается, можно сделать кнопки "пауза" и/или "прервать" - и т.п.

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

<off>
Спасибо!
</off>


 
Eraser ©   (2005-06-25 17:35) [13]

Юрий Зотов ©   (25.06.05 17:31) [12]
Ну, хотя бы только одной нормальной перерисовки формы?


Ну это можно есть processmessages вставить. Хотя конечно с потоками более универсальное решение.
Если задача на пол часа, даже на 5 минут - однозначна потоки.


 
Юрий Зотов ©   (2005-06-25 18:02) [14]

> Eraser ©   (25.06.05 17:35) [13]

> processmessages вставить.

Есть атомарная (т.е. неразрывная, внутрь которой не влезешь) достаточно длительная операция. Куда вставлять ProcessMessages?

Некуда...
:-(


 
jack128 ©   (2005-06-25 18:53) [15]

Юрий Зотов ©   (25.06.05 18:02) [14]
Есть атомарная (т.е. неразрывная, внутрь которой не влезешь) достаточно длительная операция.

Ну в этом случае, конечно никак. Только в поток эту процедуру пихать..
НО 1) Такие операции (ИМХО) достаточно редко на практике встречаются
  2) Пихание в поток - это тоже в сомнительное удовольствие, так как коли операция АТОМАРНА , то ты не сможешь завершить её когда те этого хочется.. Ну кроме TerminateThread, но этот вариант не стит рассматривать.. Это все к тому, что лудше вообще не допускать подобных операций..


 
dUM ©   (2005-06-25 23:06) [16]

В моей проге есть операции как на несколько секунд, но отображение окна необходимо, так и на несколько десятков минут. Но они не атомарные, потоки я не создаю, а окна перерисовываются по processmessages. Уж не знаю тонкостей - хорошо это или плохо, но работает! :)


 
Юрий Зотов ©   (2005-06-26 02:55) [17]

> jack128 ©   (25.06.05 18:53) [15]

> лудше вообще не допускать подобных операций..

Лудше-то, оно, конечно, лудше... да вот только не всегда возможно. Какой-нить шибко хитрый Select для заполнения контролов формы - простейший пример.

В то же время, стоит лишь написать простейшую компонентскую оболочку вокруг TThread - и задачка решается универсально, без проблем, раз и навсегда.


 
lookin ©   (2005-06-26 03:01) [18]

>>Показываете форму с прогрессбаром модально, а код выполняете в
>>отдельном потоке

Зачем в отдельном потоке?


 
Германн ©   (2005-06-26 03:07) [19]

2 Юрий Зотов ©   (26.06.05 02:55) [17]

Юр, только не пинай меня сразу! :)

"Select" - это из баз данных? Если так, то причем тут мы все? Ну да, они там что-то делают, а мы тут расхлебываем. :(

Пока что вижу только одну причину использовать отдельную нить - мат. вычисления.


 
Юрий Зотов ©   (2005-06-26 11:03) [20]

> lookin ©   (26.06.05 03:01) [18]

> Зачем в отдельном потоке?

См. [10]-[14]. Вот иллюстрирующий пример. Запустите любую оконную программу (хотя бы справку) и сдвиньте ее окно к краю экрана. Теперь запустите Delphi - появится заставка. "Повозите" окном справки по окну заставки и обратите внимание, как фигово эта заставка перерисовывается.

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

Бросьте на форму кнопку, а в ее обработчике напишите длительный цикл, на пару минут. Пусть он даже ничего не делает, а просто имитирует какую-то длительную операцию. Запустите программу, нажмите кнопку и пока выполняется этот цикл, тоже "повозите" по окну своей программы любым другим окном. Нравится Вам такая программа? Мне - нет.

ОК, теперь меняем схему. Выносим тот же самый длительный цикл в отдельный поток, а кнопка теперь пусть запускает не сам цикл, а этот поток. Повторяем эксперимент с перекрытием окон и получаем совершенно другую картину. Вот такая программа мне уже нравится. А Вам?

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

> Германн ©   (26.06.05 03:07) [19]

> "Select" - это из баз данных? Если так, то причем тут мы
> все? Ну да, они там что-то делают, а мы тут расхлебываем.


Кто отвечает перед конечным юзером за качество программы - ее разработчик, или разработчик используемой ею СУБД? Вот причем тут мы. Приходится расхлебывать, никуда не денешься.

> Пока что вижу только одну причину использовать отдельную
> нить - мат. вычисления.


Мат. вычисления, обработка файлов, вообще любая длительная операция с любыми данными. Даже просто StringReplace с очень длинным текстом.


 
lookin ©   (2005-06-26 11:33) [21]

[20] Юрий Зотов ©   (26.06.05 11:03)

Это верно, мне самому не очень нравится, что окно программы нерисовабельно во время длительных операций... Я потоки не использую. Однако при выполнении действия прогресс-бар у меня адекватно отображает ход процесса, и содержимое модального окна тоже перерисовывается. Через Processmessages... Другое дело, что главное окно уже не перерисовывается...


 
Юрий Зотов ©   (2005-06-26 12:15) [22]

> lookin ©   (26.06.05 11:33) [21]

> Через Processmessages...

См. [14], [15] и [17]. Пока не завершится длительная атомарная операция, никакой ProcessMessages не поможет. Поскольку сработает только после ее завершения. Заставка Delphi - тому пример.


 
lookin ©   (2005-06-26 12:36) [23]

[22] Юрий Зотов ©   (26.06.05 12:15)
>>Пока не завершится длительная атомарная операция

Только если она длительная. В моем случае длительность такой атомарной операции составляет не более полусекунды.


 
Юрий Зотов ©   (2005-06-26 15:17) [24]

> lookin ©   (26.06.05 12:36) [23]

> Только если она длительная.

Так о них и речь. Если нет длительных операций, то нет и вообще никаких проблем.


 
lookin ©   (2005-06-26 16:40) [25]

[24] Юрий Зотов ©   (26.06.05 15:17)

Погодите, может неправильно понял термин "атомарная операция"? Я под ней разумею некий набор действий, который выполняется один раз.  У меня длительность такого выполнения, скажем, 0,5 секунды. Теперь в цикле я выполняю этот набор действий, скажем, 1000 раз. Тогда длительность всего выполнения будет 500 секунд, и вот как раз между двумя соседними атомарными операциями я использую Application.ProcessMessages


 
Eraser ©   (2005-06-26 16:43) [26]

lookin ©   (26.06.05 16:40) [25]

Термин "атомарная" вообще обозначает операцию, которая выполняется одной командой процессора, но в данном контексте - это операция, которую нельзя прервать с пом. ProcessMessages, типа SQL запроса или копирования файла.


 
Германн ©   (2005-06-27 02:13) [27]

2 Юрий Зотов ©   (26.06.05 11:03) [20]

>> Германн ©   (26.06.05 03:07) [19]

>> "Select" - это из баз данных? Если так, то причем тут мы
>> все? Ну да, они там что-то делают, а мы тут расхлебываем.

>Кто отвечает перед конечным юзером за качество программы - ее >разработчик, или разработчик используемой ею СУБД? Вот причем >тут мы. Приходится расхлебывать, никуда не денешься.

Отвечаем и расхлебываем КОНЕЧНО МЫ! Но как порой это сложно!

Иногда я рад, что единственная моя "продажная" программа была изначально сделана на Д1 под W3.11! (Т.е. IDAPI и Paradox). Тут хоть RxLib что-то имеет. :)


 
evvcom ©   (2005-06-27 09:35) [28]


> Отвечаем и расхлебываем КОНЕЧНО МЫ! Но как порой это сложно!

Что касается баз данных, то выбор базы определяется в основном пожеланиями заказчика. Если в его пожеланиях локальные базы, то мы можем постараться убедить его в ненадежности, неудобности и пр. их использования. Серверные же боле-менее работают нормально. Поэтому чаще всего, если что-то работает не так, как следовало бы, то это действительно уже наши огрехи. Имхо. :)


 
TUser ©   (2005-06-27 10:13) [29]

> В то же время, стоит лишь написать простейшую компонентскую оболочку вокруг TThread - и задачка решается универсально, без проблем, раз и навсегда.

Что имеется ввиду под "оберткой"? Введение дополнительной функции принудительного завершения потока через TerminateThread?


 
Юрий Зотов ©   (2005-06-27 14:45) [30]

> TUser ©   (27.06.05 10:13) [29]

Да просто компонент, который можно легко бросить на форму и настроить в ИО. Вызываем его метод Execute, тот создает поток, настраивает его по свойствам компонента и запускает. Код потока реализуется пользователем в обработчике события компонента.

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



Страницы: 1 вся ветка

Текущий архив: 2005.07.18;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.049 c
1-1119788329
начинающий
2005-06-26 16:18
2005.07.18
Как определить, пуста ли определенная папка?


4-1116826440
rokstar
2005-05-23 09:34
2005.07.18
Задать кнопки "Пуск" картинку в ХР


1-1119609462
JTAG
2005-06-24 14:37
2005.07.18
Вычистить остатки компонента из программы как?


14-1119723874
Иксик
2005-06-25 22:24
2005.07.18
Как легче всего доехать из Москвы в Питер?


14-1120006103
Витёк
2005-06-29 04:48
2005.07.18
Изменить память по адресу