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

Вниз

Процессы   Найти похожие ветки 

 
Neket   (2006-12-28 11:08) [0]

Подскажите как лучше сделать. Есть прога которая по таймеру (каждые 15 мин) запускает одну процедуру. Которая работает где-то мин 8-10. (Осуществляет опрос параметров оборудования). И при этом она не "реагирует" на внешнее воздействие (ну типа подвисает). Вопрос в следущем. Как сделать выполнение этой процедуры так чтобы можно в момент её выполнения я мог её остановить. Подскажите пожалуйста возможные варианты решения этого вопроса.
P.S.
Пробовал её выполнять отдельным процессом но это не помогло (всеравно подвисает) но я не исключаю что я его не совсем корректно запустил (процесс).


 
palva ©   (2006-12-28 11:15) [1]

Чтобы не подвисало, нужно запускать процедуру в отдельном потоке (Thread), а не в процессе.
Посмотрите для этого класс TThread. Несложно работать и через API функции (CreateThread и т. д.)


 
Desdechado ©   (2006-12-28 11:21) [2]

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


 
Neket   (2006-12-28 11:23) [3]

может я просто не совсем корректно объяснил по поводу процессов. Я использовал Thread Object


 
Neket   (2006-12-28 11:28) [4]

2 Desdechado: Я думал по этому поводу... Но дело в том что у меня даже нажать на кнопку не получается. Все висит.


 
iXT ©   (2006-12-28 11:32) [5]


> Neket   (28.12.06 11:23) [3]

Thread - это не процесс, а поток (чувствуешь разницу). И чего, как делал? Как останавливал?
Ответ на вопрос ИМХО [1]. Других не задавал, ничего не описал. ???


 
Джо ©   (2006-12-28 11:32) [6]

Телепатирую. Вероятно, вся работа потока происходит в методе, вызываемом через Synchronize().


 
Neket   (2006-12-28 11:35) [7]

2 Джо: ЗачОт... :-) Именно так и делал. Если это не правельно (что-то мне подсказывает что так оно и есть) то подскажите как необходимо сделать.


 
Neket   (2006-12-28 11:38) [8]

procedure SNMP_Q.Execute;
begin

 Synchronize(StartOpros);
 { Place thread code here }
end;


 
jack128 ©   (2006-12-28 11:41) [9]

Neket   (28.12.06 11:38) [8]
Ещё одна жертва Архангельского??

Надо так:
procedure SNMP_Q.Execute;
begin
StartOpros;
end;

А в Synchronize выноси, только тот код, который работает с интефейсом...


 
Джо ©   (2006-12-28 11:42) [10]

> [7] Neket   (28.12.06 11:35)
> 2 Джо: ЗачОт... :-) Именно так и делал. Если это не правельно
> (что-то мне подсказывает что так оно и есть) то подскажите
> как необходимо сделать.

Syncronize() употребляется для выполнение переданного ей метода в контексте основного потока — того, в котором, собственно, выполняется пользовательский интерфейс (поэтому интерфейс и «виснет»). Соответственно, решение — не выполнять основную работу потока в этом методе, а выполнять его в Execute. Схема проста:

procedure XXX.Execute;
begin
 while not Terminated do
 begin
   //
   // «основная» работа потока
   //

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

  // тут проверяем условие выхода из потока,
  // если нужно, вызываем Terminate
 end;
end;

P.S. Телепатирую еще раз. Это Архангельский так научил с TThread работать? :D


 
Desdechado ©   (2006-12-28 11:43) [11]

> Но дело в том что у меня даже нажать на кнопку не получается. Все висит.
Вставь в процедуру опроса (она ж явно циклическая) в каждую итерацию Application.ProcessMessages


 
Neket   (2006-12-28 12:00) [12]

2 Джо: Да нет... Просто методом проб и ошибок. Я впринципе раньше работал с TThread. Но забыл. :-(

2 ALL: Всем спасибо буду пробовать. Если что ещё спрошу.
P.S. Ещё раз всем спасибо.


 
Ega23 ©   (2006-12-28 12:02) [13]


> Телепатирую. Вероятно, вся работа потока происходит в методе,
>  вызываемом через Synchronize().
>


Мне, кстати, это тоже первое, что пришло в голову...  :о)


 
Джо ©   (2006-12-28 12:05) [14]

> [13] Ega23 ©   (28.12.06 12:02)
>
> > Телепатирую. Вероятно, вся работа потока происходит в
> методе,
> >  вызываемом через Synchronize().
> >
>
>
> Мне, кстати, это тоже первое, что пришло в голову...  :о)

Значит, пора уже организовывать Клуб «Любителей» Архангельского :)


 
Ega23 ©   (2006-12-28 12:15) [15]


> Значит, пора уже организовывать Клуб «Любителей» Архангельского
> :)


http://delphimaster.net/view/15-1166707484/
аккурат неделю назад...   :о)


 
Neket   (2006-12-28 16:16) [16]

Все вроде заработало... Нотеперь не пойму.... А как правельно "прибить" процесс? т.е.

procedure TForm1.Button1Click(Sender: TObject);
begin
snmp_p.Create(false); // Создаем процесс
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
????????????? // Прибиваем процесс
end;


 
Джо-со-смарта   (2006-12-28 16:34) [17]

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


 
Neket   (2006-12-28 16:36) [18]

2 Джо-со-смарта: А какой пример?


 
Ega23 ©   (2006-12-28 16:38) [19]

TMyTread.Execute
beign
 While not Terminated do Work;
end;


 
Джо-со-смарта   (2006-12-28 16:38) [20]

Он у меня один в этой ветке.


 
Neket   (2006-12-28 16:58) [21]

2 Джо: Я просто немного запутался с никами...
Насколько я понял While not Terminated do Work это остановка выполнения процесса. Но а как его прибить полностью? К примеру в случае FormClose
пробовал делать так:

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Potok.Destroy;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
Potok.Terminate;
end;


Но если закрываю приложение то оно у меня зависает. Подскажите пожалуйста где ошибка?


 
Джо ©   (2006-12-28 17:19) [22]

Еще раз.
Terminate — выставляет свойство Terminated в True. Ты в своем цикле (или где-там у тебя обработка) периодически проверяешь этот свойство, и, если оно True, просто выходишь из тела метода Execute.


> [21] Neket   (28.12.06 16:58)
> Насколько я понял While not Terminated do Work это остановка
> выполнения процесса.

Нет. Это собственно сама работа твоего потока.


 
Джо ©   (2006-12-28 17:19) [23]

И не забудь перед запуском потока выставить FreeOnTerminate. Тогда экземпляр объекта будет автоматически освобожден.


 
Джо ©   (2006-12-28 17:21) [24]

Схема словами:

procedure XXX.Execute;
begin
 // что-то сделали

 // проверим, если True, то выходим из Execute

 // что-то сделали

 // проверим, если True, то выходим из Execute

 // что-то сделали

 // проверим, если True, то выходим из Execute

 // ...
end;


 
Джо ©   (2006-12-28 17:22) [25]

> проверим, если True,

проверим, если Terminated = True

Сорри.


 
Mickey74 ©   (2006-12-28 21:39) [26]

Не очень хороший способ, но попробуй:
 Application.ProcessMessages;


 
Neket   (2006-12-29 10:27) [27]

2 ДЖО: Спасибо очень помог...
Но возник ещё один вопрос как определить был ли создан поток snmp_p.Create(false); ?
Это необходимо чтобы в случае закрытия формы TForm1.FormClose при запущенном потоке чтобы поток очередную итерацию цикла доработал до конца а потом закрылся. Да и плюс ко всему, если поток не был создан и закрывается форма то вылитает ошибка
т.е. грубо говоря надо чтобы при событии OnFormClose отрабатывалась что-то вы этом роде >>> if Potok.Terminate=false then Potok.Terminate; Но как это правельно описать я к сожелаения не знаю.


 
Ega23 ©   (2006-12-29 10:32) [28]


> т.е. грубо говоря надо чтобы при событии OnFormClose отрабатывалась
> что-то вы этом роде >>> if Potok.Terminate=false then Potok.
> Terminate; Но как это правельно описать я к сожелаения не
> знаю.



 if Assigned(DataThread)  then // Если поток создан
  begin
   DataThread.Terminate; // Послали убийство
   WaitForSingleObject(DataThread.Handle, 1000); // Подождали, чтобы убился
  end;


 
evvcom ©   (2006-12-29 10:41) [29]

> [27] Neket   (29.12.06 10:27)
> чтобы в случае закрытия формы TForm1.FormClose при запущенном
> потоке чтобы поток очередную итерацию цикла доработал до
> конца а потом закрылся

Это поток сам проверяет в своем деструкторе. См. исходники.

> при событии OnFormClose отрабатывалась что-то вы этом роде
> >>> if Potok.Terminate=false then Potok.Terminate;

Во-первых, if Potok.Terminated, а во-вторых, это неважно. Просто делай Potok.Terminate. См. исходники.


 
evvcom ©   (2006-12-29 10:44) [30]

> [28] Ega23 ©   (29.12.06 10:32)

Достаточно просто DataThread.Free; во Free проверится Assigned, а в Destroy выполнится Terminate и WaitFor


 
EvChul ©   (2006-12-29 10:47) [31]

Ega23 ©   (29.12.06 10:32) [28]

А не лучше ли ?

if Assigned(DataThread)  then // Если поток создан
 begin
  DataThread.Terminate; // Послали убийство
  DataThread.WaitFor; // Подождали, чтобы убился
 end;


 
Ega23 ©   (2006-12-29 10:55) [32]


> Достаточно просто DataThread.Free; во Free проверится Assigned,
>  а в Destroy выполнится Terminate и WaitFor


Да? НУ ладно, буду знать, я с потоками мало работал.


 
Neket   (2006-12-29 10:59) [33]

Всем спасибо за помощь.... Разобрался... Попробовал все методы и работают все три но как показала практика что наиболее практичнее для ленивых ;-) писать DataThread.Free;


 
evvcom ©   (2006-12-29 11:03) [34]

> [33] Neket   (29.12.06 10:59)

А самые работящие могут написать свой или хотя бы скопировать весь код TThread в свой модуль и пользовать его. :)



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

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

Наверх




Память: 0.55 MB
Время: 0.07 c
15-1167505067
default
2006-12-30 21:57
2007.01.21
Arash feat. Aleena - Chori Chori


15-1167399180
zdm
2006-12-29 16:33
2007.01.21
Надеюсь последний вопрос в уходящем году :)


2-1167251250
Fus1on
2006-12-27 23:27
2007.01.21
Проблема с Хендлом окна.


1-1164377393
DelphiLexx
2006-11-24 17:09
2007.01.21
DBGridEh сделать Footer не внизу а после последней строкой


3-1162205718
oleg_v
2006-10-30 13:55
2007.01.21
как обнулить (обновить) поле Autoincrement(+)