Форум: "Основная";
Текущий архив: 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