Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.05.16;
Скачать: CL | DM;

Вниз

Потоки в "Дельфевых" библиотеках   Найти похожие ветки 

 
YuRock ©   (2004-04-28 14:33) [0]

Доброго всем дня! Вот нужно мне написать плугин, который работает с железякой ч-з Com-порт.
Вначале я написал экзешник (для тестов, да и отлаживать exe удобнее, чем dll) - в потоке опрашиваю Com-порт, ну и, кое-что делаю. Когда полностью отладился, все заработало - решил перенести функциональность в dll.

И тут началось самое интересное! В dll я сделал отдельный модуль, который выглядит примерно так:


unit Point;
interface
implementation

uses
 Windows, Classes;

type
 TMyThread = class(TThread)
 public
   procedure Execute; override;
 end;

var
 Thread: TMyThread;

procedure TMyThread.Execute;
begin
 MessageBox(0, "1", "", 0);
end;

initialization
 Thread := TMyThread.Create(False);
 if True then // здесь у меня своя проверка на то, что "все нормально проинициализировалось"
   ExitCode := 1; // если не "все нормально проинициализировалось" - сделать так, чтобы LoadLibrary вернула 0

finalization
 Thread.Free;

end.


Так вот, до TMyThread.Execute даже не доходит! Ну это ладно, еще можно понять... Но зачем же тогда намертво виснуть на "Thread.Free"?!!
Если конкретнее, виснет на выполнении WaitFor, который вызывается в TThread.Destroy. Что посоветуете, мастера? У меня в библиотеке не один и не два потока, и все они инициализируются, и на Free все вешаются.

Кстати, мастера, объясните, как работает параметр CreateSuspended в TThread.Create, если в BeginThread все равно передается CREATE_SUSPENDED, даже если CreateSuspended=False:

FSuspended := CreateSuspended;
FCreateSuspended := CreateSuspended;

FHandle := BeginThread(nil, 0, @ThreadProc, Pointer(Self), CREATE_SUSPENDED, FThreadID);

if FHandle = 0 then
 raise EThread.CreateResFmt(@SThreadCreateError, [SysErrorMessage(GetLastError)]);

А то что-то не понятно мне. Спасибо.


 
Digitman ©   (2004-04-28 14:51) [1]

крайне некорректно, а в ряде случаев и недопустимо манипулировать созданием/разрушением потоков в секциях инициализации/финализации модулей библиотеки

кр.того, если уж ты стартовал поток в разделе иниц-ции, какое право ты имеешь возвращать ExitCode = 1 ? Ведь поток уже стартован, а ты извещаешь систему об ошибке инициализации ! До раздела финализации вообще дело не дойдет, поскольку этот  раздел вызывается при выгрузке библиотеки, но она системой не загружена даже, ты сам этому посодействовал, вернув ExitCode = 1


 
YuRock ©   (2004-04-28 14:59) [2]

> До раздела финализации вообще дело не дойдет

Да нет, доходит как раз (я и в отладке смотрел, и в файл выводил). Но даже так - тоже вешается (вообще без finalization):


initialization
Thread := TMyThread.Create(False);
if True then begin
  Thread.Free;
  ExitCode := 1; // чтобы LoadLibrary вернула 0
end;


А как быть? У меня инициализация очень большая! Идет секунд 15. Куча чего делается. Что, отдельную ф-цию делать? Тогда прийдется весь проэкт перелапачивать и все плугины (уже написанные), и работу с ними менять!


 
YuRock ©   (2004-04-28 15:06) [3]

> Digitman ©   (28.04.04 14:51) [1]
> крайне некорректно, а в ряде случаев и недопустимо манипулировать созданием/разрушением потоков в секциях инициализации/финализации модулей библиотеки

Объясните, пожалуйста, причины этого Вашего высказывания.


 
Digitman ©   (2004-04-28 15:06) [4]


> Что, отдельную ф-цию делать? Тогда прийдется весь проэкт
> перелапачивать


а это уже твои проблемы ...
еще раз повторяю - нельзя этого делать в иниц-ции/финал-ции !


 
YuRock ©   (2004-04-28 15:08) [5]

> еще раз повторяю - нельзя этого делать в иниц-ции/финал-ции !

Еще раз прошу: можете объяснить, почему?


 
YuRock ©   (2004-04-28 15:17) [6]

И еще: никто не может дать ответ на второй вопрос (как работает (используется) параметр CreateSuspended в TThread.Create), если он при создании потока не используется:

constructor TThread.Create(CreateSuspended: Boolean);
begin
 inherited Create;
 AddThread;
 FSuspended := CreateSuspended;
 FCreateSuspended := CreateSuspended;

 FHandle := BeginThread(nil, 0, @ThreadProc, Pointer(Self), CREATE_SUSPENDED, FThreadID);
 if FHandle = 0 then
   raise EThread.CreateResFmt(@SThreadCreateError, [SysErrorMessage(GetLastError)]);
end;

?


 
Digitman ©   (2004-04-28 15:28) [7]


> YuRock ©   (28.04.04 15:17) [6]


по [6] комментариев не имею - пользую исклн-о Д5 ... в ней все ясно и корректно


> почему?


как минимум потому что я понятия не имею. что у тебя творится в Execute()


 
panov ©   (2004-04-28 15:45) [8]

>YuRock ©   (28.04.04 15:17) [6]

Если уж идти по цепочке, то дальше.

function BeginThread(SecurityAttributes: Pointer; StackSize: LongWord;
 ThreadFunc: TThreadFunc; Parameter: Pointer; CreationFlags: LongWord;
 var ThreadId: LongWord): Integer;
var
 P: PThreadRec;
begin
 New(P);
 P.Func := ThreadFunc;
 P.Parameter := Parameter;
 IsMultiThread := TRUE;
 Result := CreateThread(SecurityAttributes, StackSize, @ThreadWrapper, P,
   CreationFlags, ThreadID);
end;


 
YuRock ©   (2004-04-28 15:53) [9]

> Digitman ©   (28.04.04 15:28) [7]
> как минимум потому что я понятия не имею. что у тебя творится в Execute()

Я же написал пример!!! В Execute() у меня творится "ничего" (в данном примере - вызо ф-ции MessageBox()) - и все!!! Этого достаточно! До нее не доходит! Почему?

> panov ©   (28.04.04 15:45) [8]
> Если уж идти по цепочке, то дальше.

Ну и что? При чем здесь реализация BeginThread? В CreationFlags ф-ции CreateThread же как раз всегда и передается CREATE_SUSPENDED, который передается в BeginThread, который вызывается в TThread.Create!


 
YuRock ©   (2004-04-28 15:56) [10]

>Digitman
>panov
>...

Извините, что надоел вопросами. Просто не люблю использовать то, что работает (в данном случае - не работает) непонятно как и почему.


 
Digitman ©   (2004-04-28 16:02) [11]


> YuRock ©   (28.04.04 15:56) [10]


а я. знаешь ли, не люблю пустой треп на протяжении 10-ти постов без обсуждения реально представленногго проблемного кода потока


 
vl_chel ©   (2004-04-28 16:13) [12]

>>как работает параметр CreateSuspended в TThread.Create,
Если True то создает приостановленный поток

Есть подозрение что твоя инициализация прибивает работоспособность потока, возможно надо поток создавать приостановленным, а затем если прошла успешно запускать


 
YuRock ©   (2004-04-28 16:17) [13]

> Digitman ©   (28.04.04 16:02) [11]

Еще раз повторяю (з-й раз уже, однако, для нелюбителей пустого трепа). Вот проблемный код потока:


procedure TMyThread.Execute;
begin
MessageBox(0, "1", "", 0);
end;


или


procedure TMyThread.Execute;
begin
end;


или ЛЮБОЙ другой!!!


 
YuRock ©   (2004-04-28 16:23) [14]

> vl_chel ©   (28.04.04 16:13) [12]

Да что никак ни кто не поймет! У меня поток не то, что создается приостановленным, а вообще стоячим и нерабочим в любом случае!

Для особо умных, кто не верит - можете взять представленный мною пример - его достаточно, чтобы увидеть неработу. Сам пример компилится с первого раза. Осталось только вставить его в файл и сбилдить dll. Да еще LoadLibrary вызвать где-нибудь.


 
Digitman ©   (2004-04-28 16:27) [15]

в на момент загрузки и инициализации системой PE-модуля в АП хост-процесса происходит блокировка PEB процесса ... создаваемый же тобой поток требует от системы создания TEB+TIB, в ходе чего происходит обращение к крит.секции в PEB, которая на этот момент занята ... отсюда и "вис"

еще раз повторяю - убирай из иниц-ции/финал-ции работу с потоками, выноси ее на уровень эксп.ф-ций


 
panov ©   (2004-04-28 16:30) [16]

>YuRock ©   (28.04.04 16:17) [13]

Если уж с такими претензиями, то стоит пройти более внимательно по цепочке вызовов, тогда вопросов не возникнет.


 
Digitman ©   (2004-04-28 16:31) [17]


> YuRock ©   (28.04.04 16:23) [14]



> Для особо умных


"особо умные" задают этот вопрос в WinApi и не тычут при этом якобы безапелляционным аргументом, мол, в ЕХЕ у меня все Ок, так какого же хрена в ДЛЛ с тем же самым проблемы..

"особо умные" перед тем как задать вопрос прилагают все возможные усилия для постижения сист.механизма загрузки РЕ-модулей


 
panov ©   (2004-04-28 16:33) [18]

По поводу ошибки при инициализации библиотеки.
Никогда не возвращай ошибку при инициализации библиотеки из нее.
Это глюк реализации DLL в Delphi.

Потоки прекрасно работают из библиотек.

Про секцию intialization тебе уже сказали.


 
Digitman ©   (2004-04-28 16:37) [19]


> panov ©   (28.04.04 16:33) [18]



> Никогда не возвращай ошибку при инициализации библиотеки
> из нее.
> Это глюк реализации DLL в Delphi.


ну здесь ты, наверно, неправ

Halt(1) никому и ни при каких условиях не запрещено делать, разве что в хук-библиотеках - там с этим "темный лес"

а вот о том, что перед halt(1)  следовало бы освободить все занятые на этот момент ресурсы - это да, на этом конечно же следует заострить внимание ...

под ресурсами в дан.случае не подразумеваются трэды


 
panov ©   (2004-04-28 16:40) [20]

>Digitman ©   (28.04.04 16:37) [19]

Не от тебя ли была ветка про возврат ExitCode<>0 из библиотеки при ее инициализации?


 
YuRock ©   (2004-04-28 16:43) [21]

> Digitman
Я сказал, что в Exe работает лишь для того, чтобы у отвечающих не возникало вопроса о правильности кода потока (который Вы, как ни странно, задавали 2 раза), а ни как аргумент. И "какого хрена" я никогда не говорил. Я лишь спрашивал совета: как быть?

И всеже спасибо Вам.

> panov
> Никогда не возвращай ошибку при инициализации библиотеки из нее. Это глюк реализации DLL в Delphi.

Почему? Я использовал уже это. И не раз. Может, в старых версиях и глючило, но в D6 - пока проблем не было.
А мою проблему в [15] довольно понятно объяснил Digitman © - она не в Delphi заключается, так как с API-шным CreateThread было то же самое - я проверял.


 
vl_chel ©   (2004-04-28 16:55) [22]

YuRock ©   (28.04.04 16:23) [14]
Согласно вашему созданию  Thread := TMyThread.Create(False); не верю - он сразу начинает работу !!


 
YuRock ©   (2004-04-28 17:02) [23]

> vl_chel ©   (28.04.04 16:55) [22]

1. Внимание неверующих я уже неоднократно обращал на предоставленный пример.
2. Проблема уже решена (понятна) - тема закрыта.


 
Digitman ©   (2004-04-28 17:10) [24]


> panov ©   (28.04.04 16:40) [20]


от меня.
и речь там явно шла о хук-ДЛЛ


> vl_chel ©   (28.04.04 16:55) [22]



> не верю - он сразу начинает работу !!


нет, не сразу ... старту потока предшествует весьма сложный системный механизм модификации сист.структур в АП процесса ... и этот механизм тесно связан с крит.секциями


 
vl_chel ©   (2004-04-28 17:28) [25]

>>Digitman ©   (28.04.04 17:10) [24]
это знаю да но 15 сек ??

думаю вопрос не с системой



Страницы: 1 вся ветка

Текущий архив: 2004.05.16;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.202 c
14-1082740143
Goida
2004-04-23 21:09
2004.05.16
Тест 3D Mark 2001 на разных компьютерах...


1-1083319014
grover
2004-04-30 13:56
2004.05.16
как обновить экран?


7-1080708481
ГАГН
2004-03-31 08:48
2004.05.16
ярлык у программы.


1-1083070280
killer
2004-04-27 16:51
2004.05.16
Scrolling в StringList


8-1077695938
EthernalWonderer
2004-02-25 10:58
2004.05.16
Анимированный gif