![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Потоки [D7, WinXP]
Ypbi4 © (2007-10-30 08:11:00)Ситуация следующая -
По таймеру через определенный промежуток времени запускаю поток, по окончании операций он убивается. Подскажите plz, как узнать запущен ли поток? (Suspended не пойдет, т.к. поток убивается и получить его свойства нельзя)
Ypbi4 (2007-10-30 12:16:00) [1]Таймер как раз и нужен :) Сервак не локальный, т.е. в инете, -> уменьшить трафик, т.к. большинство данных повторяются (например у мну работает с snpp и постоянно проверяется статус сообщений доставлено или нет). При чем, не всегда нужны свежие данные, т.е. делать проверку через 5 часов или раз в сутки (опять же экономим трафик), Т.е. это оправдано.
Юрий Зотов © (30.10.07 10:33) [14] - спасибо :)
Сергей М. (2007-10-30 12:07:00) [2]
> Однокамушкин (30.10.07 12:02) [20]
>
>
Да и не помешает четкое понимание термина "запущенности" нити.
Сергей М. (2007-10-30 12:06:00) [3]
> Однокамушкин (30.10.07 12:02) [20]
Подозреваю, что и таймер-то ему нафих не нужен)
Однокамушкин (2007-10-30 12:02:00) [4]
> Сергей М. © (30.10.07 11:21) [19]
Не думаю, что автора стоит понимать так буквально, учитывая, что он ещё немного "плавает" в терминологии и не отличает нить от объекта... Думаю, ему было бы вполне достаточно, чтобы следующая активация Execute не запускалась бы до того, как завершится предыдущая
Сергей М. (2007-10-30 11:21:00) [5]
> нить гарантированно завершится
Не важно.
Условие автора - в каждый момент времени должен существовать не более чем один поток (именно как ОС-объект - см. термин "запущен").
Однокамушкин (2007-10-30 11:10:00) [6]
> Сергей М. © (30.10.07 09:03) [7]
> На момент обработки события OnTerminate нить не завершилась,
> ибо именно нить является инициатором этого события.
Ну и что? Выполнение Execute уже закончилось, нить гарантированно завершится, и если у неё стоит FreeOnTerminate, можно вообще забыть о её существовании, т.е. обнулить переменную cl, а если из-за этого новая нить будет создана чуть раньше, чем уничтожится старая, ничего страшного уже не произойдёт, т.к. старая будет выполнять только чисто служебный код
Сергей М. (2007-10-30 11:07:00) [7]
> сделал так
Ну сделал и сделал)
Аминь.
Ypbi4 (2007-10-30 11:05:00) [8]Круть :) мне далеко до вас:)
я сделал так
label
scan;
Begin
scan:
Begin
<код с подключением к серверу и проверками>
end;
sleep(5000);
goto scan;
end;
Сергей М. (2007-10-30 10:57:00) [9]
TScan = class(TThread)
..
private
..
FTimer: TTimer;
procedure DoOnTimer(Sender: TObject);
..
public
...
destructor Destroy; override;
...
end;
destructor TScan.Destroy;
begin
if GetCurrentThreadId <> MainThreadId then
PostThreadMessage(ThreadId, WM_QUIT, 0, 0);
inherited;
end;
procedure TScan.DoOnTimer(Sender: TObject);
begin
.. сеанс обмена с сервером ...
end;
procedure TScan.Execute;
var
Msg: TMsg;
begin
Fimer := TTimer.Create;
try
FTimer.Interval := ...;
FTimer.OnTimer := DoTimer;
FTimer.Active := True;
while not Terminated and GetMessage(Msg, 0, 0, 0) do
DispatchMessage(Msg);
finally
FTimer.Free;
end;
end;
Юрий Зотов (2007-10-30 10:33:00) [10]> Ypbi4 © (30.10.07 08:43) [3]
1. Переменную cl сделать полем формы.
2. Ввести метод формы:
procedure TForm1.ThreadFinished(Sender: TObject);
begin
cl := nil;
Statusbar1.Panels[1].Text := 'Поток завершился'
end;
3. Ввести метод формы:
procedure TForm1.LaunchThread;
begin
if cl = nil then
begin
cl := TScan.Create(True);
cl.Priority := tpLower;
cl.FreeOnTerminate := True
cl.OnTerminate := ThreadFinished;
cl.Resume;
Statusbar1.Panels[1].Text := 'Поток в работе'
end
end;
и вызывать этот метод для запуска потока
4. Проверка (если будет нужна):
if cl = nil then
... // Поток завершен
else
... // Поток работает
Детали см. в справке.
Сергей М. (2007-10-30 10:23:00) [11]Ну так и реализуй периодический обмен с сервером в самом потоке !
За каким лешим к этому нужно привлекать основной поток и таймер в этом основном потоке ?
Ypbi4 (2007-10-30 10:20:00) [12]Для того что бы через определенный промежуток времени запускать поток, в котором происходит обмен данных с сервером.
в событии OnTimer я подключаюсь к серверу и запускаю поток
Сергей М. (2007-10-30 10:10:00) [13]Объясни, начерта нужен таймер вообще?
Ypbi4 (2007-10-30 09:58:00) [14]Установил время таймера такое что бы поток не успевал закончиться до следущего OnTimer, (т.е. время выполнения операции ~ 8 сек, опрос установил на 1 сек), все выполнялось...
Ну если не сложно, то подскажите, как все таки проверить запущен ли поток? :)
Сергей М. (2007-10-30 09:23:00) [15]
> теперь работает
Нет, не работает.
Равество твоей "нилки" нулю вовсе не означает, что потока еще/уже не существует.
Ypbi4 (2007-10-30 09:11:00) [16]Исправил :)
сделал так -
В главной форме в public ввел переменную nilka:integer;
На событие OnCreate формы nilka:=0;
Затем переписал
if nilka<>0 then statusbar1.panels[1].text:='поток в работе' else
Далее в коде потока в начале операции прописал mainform.nilka:=1;
а в конце mainform.nilka:=0; теперь работает:)
Спасибо за подсказку ;)
Сергей М. (2007-10-30 09:03:00) [17]
> Однокамушкин (30.10.07 08:55) [6]
На момент обработки события OnTerminate нить не завершилась, ибо именно нить является инициатором этого события.
Однокамушкин (2007-10-30 08:55:00) [18]I>
> cl - имя потока
cl - это не "имя потока", это указатель на объект типа TThread (точнее, его наследника), который реализует нить... И ни нить, ни объект TThread ничего не знает об этом указателе, поэтому не обнуляет . Тут Юрий Зотов недавно очень хорошую аналогию приводил: указатель на объект - это что-то вроде телефона человека, записанного в чьей-то записной книжке, и когда человек умирает, ничего с этими записями не случается, они никуда не исчезают... Поэтому cl не равно nil, даже когда ни нити, ни объекта уже не существует
А MBo © (30.10.07 08:22) [1]правильную мысль высказал - назначать OnTerminate и по срабатыванию этого события определять, что нить завершилась
MBo (2007-10-30 08:54:00) [19]>следущей проверки пишет что 'поток в работе', т.е. cl<>nil,
Так и должно быть - деструктор не зануляет ссылку.
Какая вообще задача стоит?
Сергей М. (2007-10-30 08:53:00) [20]
> cl<>nil, хотя поток на самом деле не запущен
Для того чтобы cl стала равна nil, нужно соответствующее присвоение.
Ты его где-то делаешь ? Нет. Ну так а что же тогда хочешь ?)