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

Вниз

Показ формы из компонента   Найти похожие ветки 

 
Petrovich   (2008-04-17 12:30) [0]

Здравствуйте.
Есть некий компонент, наследник TComponent. В нем происходит опрос внешней очереди сообщений. Упрощенно - вызов некоторой функции (Func, например), пока она не вернет True. Процесс этот может быть достаточно долгим по времени. Дабы не уходить в "вечное" ожидание был введет "тайм-аут", т.е. некоторый промежуток времени, в течение которого происходит вызов этой функции и "засыпание" проги (Sleep(100)).
Вопрос №1. Идеологически правильно ли в цикле вызывать функцию и "слипаться" на короткий промежуток времени или правильнее сделать как-то по иному?

Далее эта структура перестала устраивать и встала следующая задача: через N секунд (5, например) после запуска цикла вызова Func выводить формочку с продолжительностью операции в секундах и возможностью по нажатию пользователем ESC прервать цикл вызова нашей функции Func. Цикл вызова Func в компоненте переделан так:
...
 frmWait.DoWait := True; // Запуск таймера, запоминание времени.
 try
   repeat
     Result := Func;
     if Result then
       Exit;
     Sleep(WAIT_INTERVAL_LENGTH);
     Application.ProcessMessages;
   until not frmWait.DoWait;
 finally
   frmWait.DoWait := False; // Остановка таймера, форма прячется.
 end;
...
Была нарисована обычная форма с таймером у которой при (frmWait.DoWait := True) включался TTimer. В обработчике OnTimer которого делается следующее:
procedure TfrmWait.TimerTimer(Sender: TObject);
var
 h, m, s, ms: Word;
begin
 // Вывод прошедшего времени на лейбу.
 txtTime.Caption := FormatDateTime("hh:nn:ss", Now - FStartTime);
 DecodeTime(Now - FStartTime, h, m, s, ms);
 // Если прошли наши 5 сек с момента запуска, то показ самой формы.
 if (not Visible) and (s > WAIT_SHOW_DELAY) then                  
   Show;
 Application.ProcessMessages;
end;
Проблема: цикл вызова Func бегает, форма инициализируется (время старта запоминается, таймер включается), но потом форма ожидания не появляется, т.е. в OnTimer мы не прилетаем.

Вопрос №2: где я надурил или как это надо написать, чтобы достич поставленной задачи?


 
tesseract ©   (2008-04-17 12:48) [1]


>  В нем происходит опрос внешней очереди сообщений. Упрощенно
> - вызов некоторой функции (Func, например), пока она не
> вернет True.


А CallBack ввернуть, или из внешней очереди сообщений WM_USER высылать никак ?


 
Сергей М. ©   (2008-04-17 12:50) [2]


> Идеологически правильно ли в цикле вызывать функцию


А есть варианты ?
Я к тому что можно обойтись и без цикла, если реализовать эту Func в части возможности асинхронной нотификации о событиях, которые она контролирует.


 
Petrovich   (2008-04-17 14:43) [3]

2tesseract, Сергей М.:

> А CallBack ввернуть, или из внешней очереди сообщений WM_USER
> высылать никак ?

Никак, это внешняя ДЛЛ-ина от господ из IBM без таких возможностей. По докам существует возможность нотификации, если работать не с очередями сообщений, а с топиками, но это немного из другой подход. Тут надо верь проект курочить, что не приемлемо.

> Я к тому что можно обойтись и без цикла, если реализовать
> эту Func в части возможности асинхронной нотификации о событиях,
>  которые она контролирует.

Т.е. или колбек/юзер_сообщение или цыкл получается?
Я думал, мало ли какие выверты Гуру могут предложить...


 
Сергей М. ©   (2008-04-17 15:03) [4]

Ну если ф-ция чужая, то можно вынести цикл в доп.поток ..


 
tesseract ©   (2008-04-17 15:39) [5]


> Никак, это внешняя ДЛЛ-ина от господ из IBM без таких возможностей.


В доп поток. IBM кстати отличаеться нормальныи отношением у документированию.


 
Petrovich   (2008-04-18 11:26) [6]

2Сергей М., tesseract:

> В доп поток.

А подробнее, "для чайника", объяснить можно?
Вообще, получается, мне асинхронный вызов надо превратить в синхронный.
В комноненте, по логике софта, мне надо отправить сообщение и получить ответ. Когда придет ответ, я не знаю. Как сюда прикрутить доп. поток?
Основной поток продолжаться не может без ответа.
Правильно ли я понял идею: создание доп. потока и "засыпание", пока флаг некий не станет True, например. Доп поток вызывает Func переодически и показывает форму с ожиданием и тикающими часиками. Если пользователь ничего не делает и приходит сообщение "извне", то сообщение передается в основной поток, флаг ожидания выставляется в True и доп. поток завершается. Если пользователь устал ждать и нажал ESC, то в основной поток передается ошибка и опять-таки выставляем влаг в True и завершаем доп. поток. В основном потоке когда будет выставлен флаг, то бесконецный цикл оканчивается и происходит анализ результата: если сообщение, то все путем и идем дальше по логике, если ошибка, то идем дальше на обработку ошибки.
Так что ли?


 
Anatoly Podgoretsky ©   (2008-04-18 11:34) [7]

> Petrovich  (18.04.2008 11:26:06)  [6]

Если не может продолжаться, то нафиг дополнительный поток, делай все в основном.


 
tesseract ©   (2008-04-18 12:05) [8]


> Вообще, получается, мне асинхронный вызов надо превратить
> в синхронный.


Как раз наоборот. У тебя сейчас синхронный.


> Основной поток продолжаться не может без ответа.


Ну так сразу бы и сказал. Не изголяйся тогда.


> Доп поток вызывает Func переодически и показывает форму
> с ожиданием и тикающими часиками.


А зачем  это ? Иконку поменяй - юзер поймёт.


 
Petrovich   (2008-04-18 14:20) [9]

2tesseract:

> Как раз наоборот. У тебя сейчас синхронный.

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

> А зачем  это ? Иконку поменяй - юзер поймёт.

Он-то ща и так видит, что процесс идет, но если сервак не отвечает 3-4 минуты и юзер хочет прекратить обработку данного запроса - вот в чем вся соль! Мне надо это окно показывать не просто так, а с возможностю обработать нажатие ESC и прервать ожидание основного потока, который вместо ответа сервера поднимет пользователю ошибку, типа "операция прервата пользователем".

зы. Плиз, направьте меня по пути решения этой проблемы и, если можно, примером или внятной ссылкой "как что и по чем". :)


 
tesseract ©   (2008-04-18 14:38) [10]

Поток + цикл + Event + WaitForSingleObject + until terminated.

Стандартный набор.


 
Сергей М. ©   (2008-04-18 14:46) [11]


> окно показывать не просто так, а с возможностю обработать
> нажатие ESC


А нафих окно нужно вообще ?

Ну запустил юзер некую длительную операцию, ты ему показал песочные часы и для особо бестолковых в статус-баре написал, мол, "Подожди, идет супер-пупер операция, для ее прерывания жмакни ESC".
Запускаешь свой цикл типа:

EscPressedFlag := False;

while not (Terminated or Func or EscPressedFlag) do
begin
 sleep(0);
 Application.ProcessMessages;
end;

if EscPressedFlag then
 .. юзер жмакнул ESC ..
else if Terminated then
 .. юзер закрывает приложение совсем ..
else
 .. Func вернула флаг готовности ..

А на форме, где юзер жмакнул кнопку для запуска операции, при KeyPreview=True обрабатываешь OnKeyPress, где ловишь ESC-жмак и тут же взводишь флаг EscPressedFlag.

Все !

Хочешь юзеру еще и время показать ?

Не вопрос - при начале операции включай таймер и в обработчике выводи время, по возврату из операции выключай таймер.


 
Petrovich   (2008-04-21 12:05) [12]

2Сергей М.:

> А нафих окно нужно вообще ?

Для начала напомню исходные: мы в компоненте, на не какой-либо форме все это ваяем, поэтому всякие

> в статус-баре написал

не прокатывают.

> Не вопрос - при начале операции включай таймер и в обработчике
> выводи время, по возврату из операции выключай таймер.

В теории, все чудненько, но на практике

> ... в OnTimer мы не прилетаем.


2tesseract:

> Поток + цикл + Event + WaitForSingleObject + until terminated.

Ок. Попробую что-то подобное изобразить...


 
Сергей М. ©   (2008-04-21 12:15) [13]


> напомню исходные: мы в компоненте


Чудненько.

Тогда все это никак не вяжется ни с формами, ни с Application, ни с таймером - ни того, ни другого, ни третьего приложение, использующее твой компонент, может не предполагать и не допускать.


 
GrayFace ©   (2008-04-21 12:29) [14]

Сергей М. ©   (18.04.08 14:46) [11], а зачем Sleep(0)?
Petrovich, не вызывается OnTimer - вызови явно после Application.ProcessMessages. if GetTickCount - InitTime > 5000 then ItsTime;


 
Сергей М. ©   (2008-04-21 12:34) [15]


> GrayFace ©   (21.04.08 12:29) [14]


> зачем Sleep(0)?


Затем чтобы не жрать попусту временные ресурсы системы.



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

Форум: "Основная";
Текущий архив: 2009.03.29;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.075 c
2-1233804054
snake-as
2009-02-05 06:20
2009.03.29
При открытии файла через OpenDialog имя файла не сохраняется


15-1232542679
Marser
2009-01-21 15:57
2009.03.29
Как насчёт KMP?


2-1233838460
Allizar
2009-02-05 15:54
2009.03.29
1C и Delphi 7


15-1232645348
Кое кто
2009-01-22 20:29
2009.03.29
Серия английских фильмов


15-1232104188
Артур Пирожков
2009-01-16 14:09
2009.03.29
Музыка. Много. Где скачать?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский