-
Loginov Dmitry © (25.04.08 13:40) [37] В конце TMyThread.Execute (или в деструкторе) выполняется присвоение MyThread := nil
о боже. Ты вообще понимаешь что делаешь? Блин, и кто-то говорил о профессионализме... В методах классах обращаться к конкретному экземпляру класса?
Игорь Шевченко © (25.04.08 14:01) [38] Тут в ветке где-то про чтение Рихтера говорили. Нафига читать Рихтера, если он в Delphi ни ухом ни рылом ?
я пожалуй даже отвечать не буду.
-
> что является главным признаком фактического завершения исполнения > поточной функции.
Возможно возможно...
Что же по Вашему является "главным признаком фактического завершения исполнения поточной функции", и как это "что" использовать в данной ситуации?
-
> о боже. Ты вообще понимаешь что делаешь? Блин, и кто-то > говорил о профессионализме... В методах классах обращаться > к конкретному экземпляру класса?
Вот и объясни мне, как здесь можно выкрутиться без подобных извращений!
-
> Loginov Dmitry © (25.04.08 15:29) [41]
Признаком фактического завершения поточной функции является либо вызов ф-ции ExitThread() либо вызов машинструкции RET верхнего уровня вложенности.
-
Loginov Dmitry © (25.04.08 15:30) [42] Вот и объясни мне, как здесь можно выкрутиться без подобных извращений!тебе что нужно? Завершить поток? Так сделай ему Terminate, поток должен своевременно проверять Terminated свойство и выходить из Execute когда оно true Если ты сделаешь FreeOnTerminate := true - это значит, что после выхода из Execute поток сам вызовет Destroy, то есть такому потоку-классу НЕ НУЖНО делать Free / Destroy. Если тебе нужно дождаться завершения работы потока - смотри функции WaitForSingleObject / WaitForMultipleObjects, или уже реализованный метод TThread.WaitFor Поэтому если смотреть твой пример [30], то при классе со свойством: FreeOnTerminate := true - правильный сценарий 3. При FreeOnTerminate := false правилен такой сценарий: MyThread.Terminate;
MyThread.WaitFor;
MyThread.Free ; Косяк может быть действительно в том, когда вызывается код из секции finalization. Я в библиотеках им не пользуюсь. Используй стандартные посылки Windows. То есть: library DllEntry;
procedure DLLEntryPoint(Reason: DWORD);
begin
case Reason:
Dll_Process_Attach: ДЕЛАЕМ ИНИЦИАЛИЗАЦИЮ БИБЛИОТЕКИ
DLL_PROCESS_DETACH: ДЕЛАЕМ ФИНАЛИЗАЦИЮ ВСЕХ ДАННЫХ БИБЛИОТЕКИ
end;
end;
begin
if DllProc = nil then
begin
DllProc := @DLLEntryPoint;
DllEntryPoint(Dll_Process_Attach);
end;
end.
-
> Пробегал2
> Косяк может быть действительно в том, когда вызывается код > из секции finalization. Я в библиотеках им не пользуюсь
Пользоваться или не пользоваться - это твое право. Но косяк с дедлоком будет в любом случае.
-
> Пробегал2... (25.04.08 15:59) [44]
> если смотреть твой пример [30], то при классе со свойством: > FreeOnTerminate := true - правильный сценарий 3
Неправильный он, как и все остальные сценарии.
-
Сергей М. © (25.04.08 16:23) [45] Но косяк с дедлоком будет в любом случае
где ты там видишь дедлок?! Словами можешь описать?
-
> Признаком фактического завершения поточной функции является > либо вызов ф-ции ExitThread() либо вызов машинструкции RET > верхнего уровня вложенности.
Вызов <> признаку!
> тебе что нужно? Завершить поток? Так сделай ему Terminate, > поток должен своевременно проверять Terminated свойство > и выходить из Execute когда оно true > > Если ты сделаешь FreeOnTerminate := true - это значит, что > после выхода из Execute поток сам вызовет Destroy, то есть > такому потоку-классу НЕ НУЖНО делать Free / Destroy. > > Если тебе нужно дождаться завершения работы потока - смотри > функции WaitForSingleObject / WaitForMultipleObjects, или > уже реализованный метод TThread.WaitFor > > Поэтому если смотреть твой пример [30], то при классе со > свойством: FreeOnTerminate := true - правильный сценарий > 3.
фигня какая-то получается. Я с [0] поста доказываю, что в finalization DLL-библиотеки все это не работает, а вы все-равно внушаете, что так правильно. Да, так правильно! Но не работает!
Все-таки, я все больше прихожу к выводу, что нужна дополнительная экспортируемая функция. С вариантом, когда Винда при выгрузке DLL срубает потоки еще до finalization, достаточно сложно что-либо другое придумать. Ведь такое обращения Windows с потоками - опасно и чревато потерей данных...
-
> Словами можешь описать?
На меня снижа шло озарение и я понял в чем главная проблема нашего мира. Мы не слышам друг друга...
PS [7]
-
> Пробегал2... (25.04.08 16:33) [47]
см. [7], там как раз объяснение "словами".
-
> Loginov Dmitry © (25.04.08 16:35) [48]
> Вызов <> признаку!
Поправлюсь - не сам вызов, а результат его исполнения.
В результате исполнения вызова ExitThread или возврата по RET управление будет передано в kernel32 и никогда более не будет передано коду поточной функции, что дает все основания для беспроблемной деаллокации участка ВАП, в котором размещался машкод поточной ф-ции.
-
В дополнение к [51] - подразумевается, что код поточной ф-ции м.б. смело удален из ВАП процесса не ранее чем завершат свое выполнение все потоки, созданные ранее с указанием этой поточной функции.
-
Loginov Dmitry © (25.04.08 16:35) [48] Я с [0] поста доказываю, что в finalization DLL-библиотеки все это не работает, а вы все-равно внушаете, что так правильно
как выяснили, в finalization это действительно не работает. Поэтому не надо этот код писать в finalization. ГДЕ НУЖНО ПИСАТЬ этот код - я написал в посте [44]
jack128_ (25.04.08 16:41) [49] На меня снижа шло озарение и я понял в чем главная проблема нашего мира. Мы не слышам друг друга...
PS [7]
теперь понял! Честное слово, почему-то пропустил пост [7], не читал его... Да, наверное так и есть.
-
> Пробегал2... (25.04.08 17:14) [53]
> не надо этот код писать в finalization. ГДЕ НУЖНО ПИСАТЬ > этот код - я написал в посте [44]
Финализация юнитов вызвается в контексте вызванной DllMain(DLL_PROCESS_DETACH), так что без разницы, где будет вызвана wait-функция ожидания завершения потока - хоть непосредственно в DllMain, хоть в finalization. Результат будет один и тот же - "не дождетесь !")
-
> Финализация юнитов вызвается в контексте вызванной DllMain(DLL_PROCESS_DETACH), > так что без разницы, где будет вызвана wait-функция ожидания > завершения потока - хоть непосредственно в DllMain, хоть > в finalization. Результат будет один и тот же - "не дождетесь > !")
И это правда! Проверено! :)
-
Сергей М. © (25.04.08 17:20) [54]странно... даже как-то бредово... А где же тогда рекомендуется завершать потоки, созданные в DLL? Ведь идеологически при DLL_PROCESS_DETACH самое место... Ну тогда я вижу один извращенный вариант, других по-моему просто нет. TMyThread = class(TThread)
private
FFinallyEvent: Thandle ;
protected
procedure execute; override;
constructor Create;
destructor Destroy;
property FinallyEvent: Thandle read FFinallyEvent;
end;
....
constructor TMyThread.Create;
begin
FFinallyEvent := CreateEvent(bla bla не помню что там надо) ;
FreeOnTerminate := true ;
ResetEvent(FFinallyEvent);
inherited Create(false) ;
end;
destructor TMyThread.Destroy;
begin
CloseHandle(FFinallyEvent);
inherited;
end;
procedure TMyThread.Execute;
begin
while not terminate
РАБОТАЕМ
SetEvent(FFinallyEvent) ;
end; Соответственно, вызовы приблизительно такие: var
MyThread: TMyThread;
...
initialization
MyThread := TMyThread.Create;
finalization
MyThread.Terminate;
WaitForSingleObject(MyThread.FinallyEvent) ;
end. впрочем, как я понимаю, код с FFinallyEvent можно и убрать. Все равно событие выставляется ДО того, как фактически поток будет завершен, просто максимально приближает ожидания момента к реальному моменту уничтожения потока... Так что можно и без event'а... Все равно судя по всему FreeLibary вернет управление, но поток будет продолжать крутиться и ВАП не будет очищено, то есть вс в порядке, в результате все равно все финализируется и беспокоится нечего. event можно использовать только как знак, что поток уже на финальной стадии завершения, то есть он уже не будет ничего никуда передавать, не будет ничего создавать и открывать и прочее...
-
> Пробегал2... (25.04.08 17:52) [56]
Практически тот же изврат, что и при while Assigned(MyThread) do... но более правильный. От срубания потоков виндой все-равно не спасет! :)
-
Loginov Dmitry © (25.04.08 18:06) [57] Практически тот же изврат, что и при while Assigned(MyThread) do... но более правильный
ну нифига... У тебя все расчитано, что максимум будет создан один поток.. Второй поток уже внесет несусветную суматоху. У меня же поток по всем правилам ООП написан ;) Поменяются тольуо функции ожидания для нескольких потоков, будет использована WaitForMultipleObjects
Loginov Dmitry © (25.04.08 18:06) [57] От срубания потоков виндой все-равно не спасет! :)
да с чего ты взял, что винда потоки срубает?!?! Винда финализирует потоки не при FreeLibrary, а при завершении процесса, тогда она все ресурсы пытается освободить, созданные этим процессом.
-
> странно... даже как-то бредово... А где же тогда рекомендуется > завершать потоки, созданные в DLL? Ведь идеологически при > DLL_PROCESS_DETACH самое место...
потоки не создаются в DLL. Потоки создаются в процессе. Познай эту истину и будет тебе рулез вечный и немеряный
|