Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2005.07.18;
Скачать: [xml.tar.bz2];

Вниз

что-то типа 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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.54 MB
Время: 0.036 c
1-1119959721
hgd
2005-06-28 15:55
2005.07.18
Алгоритм закраски "ведро"


14-1119587428
Kerk
2005-06-24 08:30
2005.07.18
Что за эпидемия талибанских вирусов?


1-1120194700
Mishenka
2005-07-01 09:11
2005.07.18
Как узнать запущена ли в данный момент другая программа?


1-1119946584
rolex
2005-06-28 12:16
2005.07.18
Как сохранить/загрузить содержимое ListView в файл?


4-1116595386
DinoRay
2005-05-20 17:23
2005.07.18
WM_COPYDATA и скрытое окно





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский