Форум: "Основная";
Текущий архив: 2004.01.09;
Скачать: [xml.tar.bz2];
ВнизПроблема с остановкой потока Найти похожие ветки
← →
Ил_204 (2003-12-22 10:21) [0]Есть поток:
procedure TMyThread.Execute;
var
i: integer;
begin
FreeOnTerminate := true;
for i := 1 to 10 do begin
Sleep(100);
beep;
end;
// FreeAndNil(self);
end;
Есть ф-ция запуска потока:
procedure TForm1.Button1Click(Sender: TObject);
var
MyThread: TMyThread;
i: integer;
begin
MyThread := TMyThread.Create(False);
for i := 1 to 1000 do begin
if not Assigned(MyThread) then begin
ShowMessage("free");
exit;
end;
sleep(10);
end;
ShowMessage("not free");
end;
Вопрос в следующем, почему не работает конструкция
not Assigned(MyThread)?
Даже FreeAndNil(self) перед завершением потока не спасает.
← →
Bart (2003-12-22 10:27) [1]Assigned в данном примере понятия не иммет каково состояние переменной MyThread. Т.к. поток содается CreateSuspend = False, да еще и в теле написано FreeOnTerminate = True.
Все поток запущен, общение с ним может осщуствляться только через сообщения.
← →
Digitman (2003-12-22 10:29) [2]
> почему не работает конструкция
> not Assigned(MyThread)?
потому что в твоем коде переменной MyThread нигде nil не присваивается, вот она все время и остается Assigned
в случае использования FreeOnTerminate = True вероятным решением будет назначение обработчика события TThread.OnTerminate() , в теле которого как раз и уместно выполнить MyThread := nil;
← →
Ил_204 (2003-12-22 10:34) [3]2Bart: Дело не в общении с потоком, нужно лишь отследить момент когда его код закончится и он выгрузиться из памяти.
2Digitman: Странно почему FreeAndNil(Self) в конце не работал?! Сейчас буду пробовать Ваш вариант.
← →
Ил_204 (2003-12-22 10:36) [4]2Digitman: В обработчике TThread.OnTerminate() не может быть MyThread := nil, только self := nil. Так?
← →
Digitman (2003-12-22 10:41) [5]
> Странно почему FreeAndNil(Self) в конце не работал?!
потому что это чушь
> В обработчике TThread.OnTerminate() не может быть MyThread
> := nil, только self := nil. Так?
не так.
> нужно лишь отследить момент когда его код закончится и он
> выгрузиться из памяти
откажись от FreeOnTerminate = True и выполняй
MyThread := TMyThread.Create(False);
MyThread.WaitFor; // ждем фактического завершения потока
FreeAndNil(MyThread); // разрушаем объект и обнуляем ссылку
← →
Ил_204 (2003-12-22 10:46) [6]А ежели поток повиснет?
← →
Digitman (2003-12-22 10:52) [7]
> А ежели поток повиснет?
с чего бы ему "повиснуть" ?
еслим логика в теле Execute корректна и предусматривает все возможные ситуации, которые могут повлиять на своевременное и безошибочное завершение потока ?
← →
Bart (2003-12-22 10:56) [8]я собственно об этом и говорю, на Free потока послать сообщение основному потоку.
А циклом проверять - как-то не красиво.
← →
Ил_204 (2003-12-22 11:02) [9]2Digitman: в потоке используется код чужих dll со всеми вытекающими...
2Bart: громоздко как-то получается :(
← →
Ил_204 (2003-12-22 11:10) [10]Конструкция была приведена к следующему виду:
procedure TForm1.Button1Click(Sender: TObject);
var
MyThread: TMyThread;
i: integer;
begin
MyThread := TMyThread.Create(False);
for i := 1 to 500 do begin
if MyThread.IsTerminated then begin
ShowMessage("free");
FreeAndNil(MyThread);
exit;
end;
Label1.Caption := IntToStr(i);
Application.ProcessMessages;
sleep(10);
end;
ShowMessage("not free");
end;
...
TMyThread = class(TThread)
private
fIsTerminated: boolean;
procedure MyTerminate(Sender: TObject);
protected
procedure Execute; override;
public
property IsTerminated: boolean read fIsTerminated;
end;
...
procedure TMyThread.Execute;
var
i: integer;
begin
fIsTerminated := false;
OnTerminate := MyTerminate;
FreeOnTerminate := false;
for i := 1 to 10 do begin
Sleep(100);
beep;
end;
end;
...
procedure TMyThread.MyTerminate(Sender: TObject);
begin
fIsTerminated := true;
end;
...
Что скажете, есть замечания?
← →
Digitman (2003-12-22 11:10) [11]
> Ил_204
и что ? ты считаешь что осн.поток должен постоянно "пасти" дополнительные на предмет, "зависли" они или "не зависли" ?
дурней не придумаешь)
единственный разумный по логике смысл этого - проверка на "живость" непосредственно перед завершением тек.процесса, иначе процесс не завершится, пока активен хотя бы один доп.код.поток ... а уж если хотя бы один поток в этой ситуации обнаружен как "зависший", то выход здесь один - скомандовать TerminateThread() , т.е. аварийно снять поток с выполнения
← →
Ил_204 (2003-12-22 11:16) [12]Нафик не уперлось постоянно его "пасти".
Основная идея: при завершении потока, если тот не умирает, то выждать заданное число таймаутов и выдать пользователю сообщение об ошибке. Далее по ситуации.
← →
Digitman (2003-12-22 11:17) [13]какой у тебя вообще критерий оценки факта "зависания" потока ?
откуда тебе знать, сколько точно времени требуется поточной ф-ции для ее выполнения ? время это зависит от множества факторов !
← →
Digitman (2003-12-22 11:20) [14]
> выждать заданное число таймаутов
откуда тебе ЗАРАНЕЕ знать, чему равно это число ?
а если потоку требуется на долю миллисекунды больше для корректного завершения, то что ? он разве "завис" ? да ты просто недождался !
← →
Ил_204 (2003-12-22 11:22) [15]определяется пользователем в настроечном файле.
← →
Digitman (2003-12-22 11:27) [16]
> Ил_204
))
да ты сам-то не знаешь, сколько времени в пределе требуется поточной ф-ции для завершения, а уж пользователю и подавно не знать) ... он что, от балды будет проставлять это время ? хочу, мол, 5 часов поставлю, а хочу - пол-секунды ?
← →
Bart (2003-12-22 11:28) [17]А неужели есть необходимость знать когда поток закончит работу? Если это обработка - запускай ее и забывай, только логи не забывай писать.
Какая конечная цель?
← →
Digitman (2003-12-22 11:40) [18]
> Ил_204
"рисую" последствия твоей логики , ч.н., "на огурцах" :
- юзер жмет кнопулю, в ответ ты стартуешь поток, который, к примеру, вызывает некую блок.ф-цию из DLL, выполняющую сложные расчеты и записывающую по ходу этих расчетов промеж.результаты в некий файл
- после старта потока ты берешь из конфиг.файла число = 5 сек (которое учтановил сам юзер перед стартом приложения, причем - от балды) и ждешь эти 5 сек на предмет факта завершения потока
- рельно вызванная в потоке DLL-ф-ция на сей момент отработает до конца не за 5 сек, а за 10 сек, через которые следовало бы ожидать нормального завершения записи в файл всей необх. по расчетам инф-ции
- по истечении 5 сек в лучшем случае ты выдаешь юзеру предупреждение и за сим успокаиваешься (хуже, если тут же принудительно терминируешь поток)
в результате в лучшем случае ты змучаешь юзера дурацкими предупреждениями (юзер-то видит, что на самом деле ожидаемый файл появился и корректен !!), в худшем - юзер будет в панике, потому что результирующий файл по каким-то непонятным ему причинам имеет совершенно неожидаемое, "огрызкообразное" содержимое !
← →
Ил_204 (2003-12-22 11:44) [19]Поток работает с устройством. Ситуация завершения потока происходит при принудительной остановке устройства(сам поток+драйвера+железка) администратором сервера. Ясное дело, что это должно произойти за конечное время, определенное админом. Продолжительность периода зависит от типа оборудования и вибирается САМИМ администратором.
Естественно, с первого раза оптимальную задержку не поставишь, но речь идет не о настройке, а об эксплуатации.
← →
mrcat (2003-12-22 11:48) [20]Ил_204 (22.12.03 11:44) [19]
>Поток работает с устройством.
А нельзя ли этим устройством, посылать потоку сигнал завершения ?
← →
Ил_204 (2003-12-22 11:50) [21]Устройства разных типов. Никак... :(
← →
Digitman (2003-12-22 11:50) [22]
> Ил_204
и что ? "устройство" не имеет асинхр.режима взаимодействия с ним ? и никаких тайм-аутов нет в помине ?
← →
alex_*** (2003-12-22 11:50) [23]или поток пинговать и в случае зависания Terminate() ?
← →
Digitman (2003-12-22 11:52) [24]
> Ил_204
ты вообще в состоянии вразумительно описать, ЧЕМ вызвана необходимость вынесения логики работы с дивайсом в доп.код.поток ?
← →
Digitman (2003-12-22 11:54) [25]
> alex_*** (22.12.03 11:50) [23]
> или поток пинговать
"пинговать" - сильно сказано)
даже не рискну полюбопытствовать, какое отношение Packet INternet Goopher имеет к код.потоку)
← →
alex_*** (2003-12-22 11:55) [26][23] : Только надо корректно определять зависания, учитывая картину [18] ))
← →
alex_*** (2003-12-22 11:56) [27]ну блин, это я иносказательно. Сообщения посылать, я имел ввиду.
← →
Digitman (2003-12-22 12:01) [28]
> Сообщения посылать, я имел ввиду
кому ? потоку ? а если он в это время корректно исполняет некий блок.вызов и попросту занят совершенно иным делом ?
PostThreadMessage ? вернет True - поток-то существует ..
Post/SendMessage ? окно нужно создавать, а надо ли оно ?
ну,предположим, создали окно, вызвали SendMessageNotify(), получили отлуп по тайм-айту, и что ? сие есть разве факт "зависания" ?!
← →
Ил_204 (2003-12-22 12:10) [29]2Digitman: 255 устройств. все в одном потоке разруливать?
← →
Digitman (2003-12-22 12:23) [30]
> 255 устройств. все в одном потоке разруливать?
да хоть 25000 !
что значит "разруливать" ?
термин дилетанта, не понимающего, как правильно организовать процесс, отделив "мух" от "котлет", т.е. "транспорт" от "обработки данных, доставляемых посредством транспорта"
а транспорт, будучи упомянутым, бывает синхронным и асинхронным, о чем ты ни слова не сказал
← →
Ил_204 (2003-12-22 12:26) [31]Всем огромное спасибо за помощь.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.01.09;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.01 c