Текущий архив: 2007.11.25;
Скачать: CL | DM;
Вниз
Потоки Найти похожие ветки
← →
Ypbi4 © (2007-10-30 08:11) [0]Ситуация следующая -
По таймеру через определенный промежуток времени запускаю поток, по окончании операций он убивается. Подскажите plz, как узнать запущен ли поток? (Suspended не пойдет, т.к. поток убивается и получить его свойства нельзя)
← →
MBo © (2007-10-30 08:22) [1]при завершении потока инициировать событие OnTerminate
← →
Сергей М. © (2007-10-30 08:25) [2]
> как узнать запущен ли поток?
Если ты его успешно "запустил", то значит он "запущен", что тут еще узнавать ?
> по окончании операций он убивается
Кем ?
← →
Ypbi4 © (2007-10-30 08:43) [3]При запуске потока прописываю свойство
cl.FreeOnTerminate:=true - по окончании процесса он самоуничтожится.
cl - имя потока
сделал проверку так
if cl <> nil then statusbar1.panels[1].text:="поток в работе" else
Begin
cl:=TScan.Create(true);
cl.Resume;
cl.Priority:=tpLower;
cl.FreeOnTerminate:=true; //прописывал так же свойство и в классе потока
statusbar1.panels[1].text:="поток запущен";
end;
Теперь он первый раз запускается, если ранее не был запущен все выполняет и должен самоуничтожиться, но почему то он при следущей проверки пишет что "поток в работе", т.е. cl<>nil, хотя поток на самом деле не запущен.. :(
← →
Сергей М. © (2007-10-30 08:53) [4]
> cl<>nil, хотя поток на самом деле не запущен
Для того чтобы cl стала равна nil, нужно соответствующее присвоение.
Ты его где-то делаешь ? Нет. Ну так а что же тогда хочешь ?)
← →
MBo © (2007-10-30 08:54) [5]>следущей проверки пишет что "поток в работе", т.е. cl<>nil,
Так и должно быть - деструктор не зануляет ссылку.
Какая вообще задача стоит?
← →
Однокамушкин (2007-10-30 08:55) [6]I>
> cl - имя потока
cl - это не "имя потока", это указатель на объект типа TThread (точнее, его наследника), который реализует нить... И ни нить, ни объект TThread ничего не знает об этом указателе, поэтому не обнуляет . Тут Юрий Зотов недавно очень хорошую аналогию приводил: указатель на объект - это что-то вроде телефона человека, записанного в чьей-то записной книжке, и когда человек умирает, ничего с этими записями не случается, они никуда не исчезают... Поэтому cl не равно nil, даже когда ни нити, ни объекта уже не существует
А MBo © (30.10.07 08:22) [1] правильную мысль высказал - назначать OnTerminate и по срабатыванию этого события определять, что нить завершилась
← →
Сергей М. © (2007-10-30 09:03) [7]
> Однокамушкин (30.10.07 08:55) [6]
На момент обработки события OnTerminate нить не завершилась, ибо именно нить является инициатором этого события.
← →
Ypbi4 © (2007-10-30 09:11) [8]Исправил :)
сделал так -
В главной форме в 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:23) [9]
> теперь работает
Нет, не работает.
Равество твоей "нилки" нулю вовсе не означает, что потока еще/уже не существует.
← →
Ypbi4 © (2007-10-30 09:58) [10]Установил время таймера такое что бы поток не успевал закончиться до следущего OnTimer, (т.е. время выполнения операции ~ 8 сек, опрос установил на 1 сек), все выполнялось...
Ну если не сложно, то подскажите, как все таки проверить запущен ли поток? :)
← →
Сергей М. © (2007-10-30 10:10) [11]Объясни, начерта нужен таймер вообще ?
← →
Ypbi4 © (2007-10-30 10:20) [12]Для того что бы через определенный промежуток времени запускать поток, в котором происходит обмен данных с сервером.
в событии OnTimer я подключаюсь к серверу и запускаю поток
← →
Сергей М. © (2007-10-30 10:23) [13]Ну так и реализуй периодический обмен с сервером в самом потоке !
За каким лешим к этому нужно привлекать основной поток и таймер в этом основном потоке ?
← →
Юрий Зотов © (2007-10-30 10:33) [14]> 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:57) [15]
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;
← →
Ypbi4 © (2007-10-30 11:05) [16]Круть :) мне далеко до вас:)
я сделал так
label
scan;
Begin
scan:
Begin
<код с подключением к серверу и проверками>
end;
sleep(5000);
goto scan;
end;
← →
Сергей М. © (2007-10-30 11:07) [17]
> сделал так
Ну сделал и сделал)
Аминь.
← →
Однокамушкин (2007-10-30 11:10) [18]
> Сергей М. © (30.10.07 09:03) [7]
> На момент обработки события OnTerminate нить не завершилась,
> ибо именно нить является инициатором этого события.
Ну и что? Выполнение Execute уже закончилось, нить гарантированно завершится, и если у неё стоит FreeOnTerminate, можно вообще забыть о её существовании, т.е. обнулить переменную cl, а если из-за этого новая нить будет создана чуть раньше, чем уничтожится старая, ничего страшного уже не произойдёт, т.к. старая будет выполнять только чисто служебный код
← →
Сергей М. © (2007-10-30 11:21) [19]
> нить гарантированно завершится
Не важно.
Условие автора - в каждый момент времени должен существовать не более чем один поток (именно как ОС-объект - см. термин "запущен").
← →
Однокамушкин (2007-10-30 12:02) [20]
> Сергей М. © (30.10.07 11:21) [19]
Не думаю, что автора стоит понимать так буквально, учитывая, что он ещё немного "плавает" в терминологии и не отличает нить от объекта... Думаю, ему было бы вполне достаточно, чтобы следующая активация Execute не запускалась бы до того, как завершится предыдущая
← →
Сергей М. © (2007-10-30 12:06) [21]
> Однокамушкин (30.10.07 12:02) [20]
Подозреваю, что и таймер-то ему нафих не нужен)
← →
Сергей М. © (2007-10-30 12:07) [22]
> Однокамушкин (30.10.07 12:02) [20]
>
>
Да и не помешает четкое понимание термина "запущенности" нити.
← →
Ypbi4 © (2007-10-30 12:16) [23]Таймер как раз и нужен :) Сервак не локальный, т.е. в инете, -> уменьшить трафик, т.к. большинство данных повторяются (например у мну работает с snpp и постоянно проверяется статус сообщений доставлено или нет). При чем, не всегда нужны свежие данные, т.е. делать проверку через 5 часов или раз в сутки (опять же экономим трафик), Т.е. это оправдано.
Юрий Зотов © (30.10.07 10:33) [14] - спасибо :)
Страницы: 1 вся ветка
Текущий архив: 2007.11.25;
Скачать: CL | DM;
Память: 0.53 MB
Время: 0.021 c