Текущий архив: 2005.03.20;
Скачать: CL | DM;
Вниз
Исключение в деструкторе треда при попытке протрассировать его Найти похожие ветки
← →
Fktrc © (2005-03-04 09:54) [0]Завершаю потоки при закрытии приложения
Содержание деструктора
destructor TItemThread.Destroy;
begin
Terminate;
SetEvent(FStopEvent);
WaitFor;
CloseHandle(FStopEvent);
DeleteCriticalSection(...);
inherited
end;
После остановки на бряке в этом деструкторе(точку можно ставить в нем где угодно) нажатие F7 F8 дает эксцепшен Access Violation и иногда EExternalException (точное название не помню).
Причем, если точку останова в деструкторе не ставить, отрабатывает без исключений и при запуске из среды, и при самостоятельном запуске.
Этот же деструктор при завершении потока НЕ при закрытии приложения трассируется без исключений...
Два вопроса
- почему так происходит?
- стоит ли переходить на OnTerminate?
← →
Erik1 © (2005-03-04 10:05) [1]У тебя странная вещь написана зачем тебе Terminate и SetEvent(FStopEvent) одновремено? По событию StopEvent делаей выход из execute. И ходелось бы увидеть твой метод execute, каким образом ты ожидаеш событие, на какой строчке происходит exception, какя процедура вызвала Destroy(Free), стек вызовов также приведи.
← →
Digitman © (2005-03-04 10:10) [2]
> почему так происходит?
мало ли почему ... например при более чем однократном вызове деструктора со стороны более чем одного трэда .. смотрю, ты крит.секцию пользуешь - а ведь явно некорректно пользуешь ее !
да и вообще - код деструктора выглядит по меньшей мене странно, если не сказать подозрительно ..
> - стоит ли переходить на OnTerminate?
а с какого боку тут OnTerminate ?
это просто событие, извещающее о том что исполнение метода Execute() на сей момент успешно завершено .. к тому же вызов обработчика OnTerminate синхронизирован с трэдом, Ид которого хранится в MainThreadId
← →
Digitman © (2005-03-04 10:18) [3]destructor TItemThread.Destroy;
begin
EnterCriticalSection(...);
try
if GetCurrentthreadId <> MainThreadId then
PostThreadMessage(ThreadId, WM_QUIT, 0, 0);
inherited;
finally
LeaveCriticalSection(...);
DeleteCriticalSection(...);
end;
end;
procedure TItemThread.Execute;
begin
..
while not Terminated GetMessage(..) do
begin
...
end;
..
end;
← →
Fktrc © (2005-03-04 11:26) [4]Мда... маразм крепчал, шиза косила наши ряды...
Спасибо всем. Буду искать свой глюк. Тем более что, как видно, тут не просто глюк, а зияющий провал в знаниях о многопоточности...
← →
Digitman © (2005-03-04 11:29) [5]
> Fktrc © (04.03.05 11:26) [4]
> зияющий провал в знаниях о многопоточности
"Эт точно !" (с) Федор Сухов
)
← →
Eraser © (2005-03-04 11:38) [6]Fktrc ©
имхо лучший вариант проведения удаления разных объектов и хендлов (финализации) осуществлять сразу за основным циклом в OnExecute.
← →
Digitman © (2005-03-04 12:38) [7]
> Eraser © (04.03.05 11:38) [6]
в ряде случаев вариант с созданием/уничтожением объектов не иначе как в Execute() (и искл-но там же - работой с ними) попросту не удобен ... или недопустим по логике ...
зачастую требуется иметь УЖЕ созданный или УЖЕ уничтоженный объект ВНЕ зависимости от того, работает ли доп.трэд как ОС-объект (которому так же по логике требуется обращение к объекту) или же он приостановлен/терминирован
так что никаких четких рекомнедаций к тому, где создавать или уничтожать объект, нет и быть не может - все зависит от конкретной сквозной логики
← →
Eraser © (2005-03-04 13:07) [8]Digitman ©
Ну да, в плане хэндлов я легка перегнул, т.к. в основном это хэндля синхронизирующих объектов, которые используют другие потоки...
Но что касается внутренних объектов потока, то лучше [6].
Страницы: 1 вся ветка
Текущий архив: 2005.03.20;
Скачать: CL | DM;
Память: 0.49 MB
Время: 0.031 c