Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.05.16;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.031 c
7-1081145534
Clawhammer
2004-04-05 10:12
2004.05.16
Установка Time Zone...


3-1082054430
td
2004-04-15 22:40
2004.05.16
onFilterRecord


6-1080082331
AleXR
2004-03-24 01:52
2004.05.16
Как установить соединение DialUp


1-1083235519
Vlad Oshin
2004-04-29 14:45
2004.05.16
Chartfx. Как построить _любой_ график


1-1083139999
Ivolg
2004-04-28 12:13
2004.05.16
Перевести





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский