![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Почему у потока вызывается Terminate? [D6, Win2k]
Aleksandr © (2002-03-15 14:03:00)Есть у меня поток. Существует он в одном экземпляре,
Execute у него обыкновенный:
begin
repeat
if FoundFiles then
DoChanges;
Sleep(500)
until Terminated
end;
Долго я искал, почему сей поток у меня периодически перестает работать, пока не догадался перекрыть ему OnTerminate. И оказалось, что он по непонятным причинам просто делает Terminate.
Почему это происходит и как сделать, чтобы он не Terminate до завершения работы программы?
kull (2002-03-16 03:51:00) [1]Ну конечно! Как только ни фига не выходит, так сразу Delphi виноват или Windows глючный.
А может просто на код посмотреть внематочно?
Чудес не бывает!
Aleksandr (2002-03-15 19:34:00) [2]Нет, это не в Эксепте... А Инди у меня в другом месте есть, не в цикле, и его raise всю программу вышибает...
digitman (2002-03-15 18:31:00) [3]Ах, вон оно что !
Так ведь, если это исходнике, на который ты пеняешь, все же выглядит вот так :
...
except
...
if Handler.Active then
...
else Raise;
end;
то это - абсолютно нормальная и корректная ситуация !
тем самым некое возникшее исключение, невозможное для обработки на данном уровне вложенности, возбуждается для потециально возможной обработки на предыдущем уровне вложенности вызовов подпрограмм !
digitman (2002-03-15 18:24:00) [4]и какой еще Инди там у тебя вдруг появился в АБСОЛЮТНО пустом цикле в Execute при стандартном конструкторе - тоже непонятно)
см.
digitman © (15.03.02 15:15)
и
Aleksandr © (15.03.02 15:51)
Aleksandr (2002-03-15 18:24:00) [5]дык в том-то и дело... код в исходнике Indy:
...
if Handler.Active then
...
else Raise;
end;
Переделал ему это дело, объявив новый потомок TException, и пошло как по маслу... Кстати, уже не первый раз такое встречаю, в основном, когда программы с Делфи 3 перерабатываю...
digitman (2002-03-15 18:20:00) [6]хммм... что ж это за "пустой Raise" такой ?)
вот загадка так загадка !)
DieHard (2002-03-15 18:13:00) [7]какие-такие неопределенные?
если в except...end, то они те же самые, что его и вызвали
если вне, то дожен указываться конкретный тип
Aleksandr (2002-03-15 18:08:00) [8]Усе... нашел, кто мне гадит...
Смотря в корень, гадит Делфи, позволяя делать вызовы raise (неопределенные), и эти-то неопределенные raise Delphi и не обрабатывает... В итоге блок try..except не помогает корректно продолжить код... Ну а реально остановка была из-за вызова пустого Raise одной из компонент (Indy). Всем спасибо за поссибельную помощь :))
digitman (2002-03-15 17:12:00) [9]>Aleksandr
>>"Сделал как у тебя... Останавливается."
Конструктор потока - точно стандартный ?
Тогда следующее предположение : внешний по отношению к объекту-потоку код где-то "гадит" его поля.
Долго так еще будем гадать) ...
Андрей Сенченко (2002-03-15 16:50:00) [10]E.Free - очень хороший метод вызвать веселое сообщение о том, что"программа выполнила ..."
Тут то мы все и узнаем.
Юрий Зотов (2002-03-15 16:42:00) [11]1. E.Free вызывать не надо - Delphi разруливает такие вещи сама.
2. Напишите Execute так:
try
while not Terminated do
begin
if FoundFiles then DoChanges;
Sleep(500)
end
except
MessageBeep(0)
end;
Затем поставьте BreakPoint на MessageBeep и запустите. Если придете на эту точку, значит, дело именно в Exception. Пройдите по стеку вызовов и найдете причину.
digitman (2002-03-15 16:36:00) [12]E.Free ??????!!!!! убери его срочно !
Где, из каких источников ты взял сие ?
Aleksandr (2002-03-15 16:17:00) [13]Может быть, и так :(... Только кода дофига, да истчо и не моего, поэтому хрен его, где может raise или запись в память уйти... Есть такие моменты. Тогда вопрос в том, как предохранить поток от остановки обработчиком Except"a? Грубо говоря, как при появлении Exception его мягко убрать, чтобы он не выкидывал фокусов с выходами из методов и изменениями значений пропертей?
Делал я приколку типа
except
on E:Exception do begin
Log(E.Message)
E.Free
end
end;
Пофигу... ошибка все равно уходит в код, вызвавший метод с этим обработчиком...
digitman (2002-03-15 15:55:00) [14]во внешних блоках except, в которые заключены тела сомнительных методов, нет финального raise ? если нет, тогда единственный вариант - флаг FTerminated ты "портишь" сам того не ведая при неверных обращениях к памяти по записи
Aleksandr (2002-03-15 15:51:00) [15]2 Digitman...
Наверное, я сегодня не с той кнопки машину запускал... Мистика... Сделал как у тебя... Останавливается.
USAtyj (2002-03-15 15:41:00) [16]А память нигде не выделяешь под какие-нибудь переменные?
Я в свое время используя дополнительно длл выделял в самой длл память, вот из-за некорректности выделения, память отведенная под FTerminate переписывалась какими-либо левыми данными. Если там было записано 0 (False), то при записи любого другого числа, получалось True. По-моему в этом может быть причина.
Юрий Зотов (2002-03-15 15:30:00) [17]Если в FoundFiles или DoChanges происходит Exception, который не гасится там же, то это приведет к выходу из Execute. Соответственно, возникнет событие OnTerminate и будет вызыван его обработчик.
digitman (2002-03-15 15:15:00) [18]вот ты фома неверующий)
при условии, что тобой вызывается стандартный конструктор объекта-потока XXX запусти-ка вот это :
procedere XXX.Execute;
begin
repeat
until Terminated;
end;
цикл будет "крутиться вечно" !!!
Aleksandr (2002-03-15 15:01:00) [19]Ладно, поставим вопрос иначе... Какой из стандартных методов Потока может менять флаг FTerminated? Например, если я внутри DoChanges запустил другой поток и сделал его
Changer.Resume;
Changer.WaitFor
может ли он вызвать к прекращению основного потока?
Я сделал легкое извращение: цикл Execute базового потока
begin
repeat
if FoundFiles then
DoChanges;
Sleep(500)
until FGoTerminating
end;
FGoTerminating изменяет свое состояние в верно только при завершении программы... Однако OnTerminate все равно вызывается...
Я извратился еще больше. Просто в цикле оставил методы с пустым телом. Поток все равно прекращает свою работу... Что за нафиг...
Coalycat (2002-03-15 14:56:00) [20]Если потоков несколько, то удобно сделать так:
repeat
...
...
if ClosePortProcess.WaitFor(50)=wrSignaled
then TerminateMyThread:=true;
until TerminateMyThread;
где ClosePortProcess: TEvent, а TerminateMyThread объявлена как глобальная константа:
. Один раз Event выставил и все потоки завершатся.
const
TerminateMyThread : Boolean=false;