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