Доброго всем дня! Вот нужно мне написать плугин, который работает с железякой ч-з 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 вернула 0finalization
Thread.Free;
end.
Так вот, до TMyThread.Execute даже не доходит! Ну это ладно, еще можно понять... Но зачем же тогда намертво виснуть на "Thread.Free"?!!
Если конкретнее, виснет на выполнении WaitFor, который вызывается в TThread.Destroy. Что посоветуете, мастера? У меня в библиотеке не один и не два потока, и все они инициализируются, и на Free все вешаются.
Кстати, мастера, объясните, как работает параметр CreateSuspended в TThread.Create, если в BeginThread все равно передается CREATE_SUSPENDED, даже если CreateSuspended=False:
Добрый день!
YR>Так вот, до TMyThread.Execute даже не доходит! Ну это ладно, еще можно понять... Но зачем же тогда намертво виснуть на "Thread.Free"?!! YR>Если конкретнее, виснет на выполнении WaitFor, который вызывается в TThread.Destroy. Что посоветуете, мастера? У меня в библиотеке не один и не два потока, и все они инициализируются, и на Free все вешаются.
YR>Кстати, мастера, объясните, как работает параметр CreateSuspended в TThread.Create, если в BeginThread все равно передается CREATE_SUSPENDED, даже если CreateSuspended=False:
вот что я думаю по этому поводу...
1.будет ли для dll работать блок initialization как задумано? ведь initialization запускается при старте приложения, а библиотека может быть загружена один раз и пользоваться несколькими прогами, т.е. повторного запуска initialization не будет. у меня щас нет под рукой доки по dll, но я помню, что там для первоначальной инициализации используется какая-то процедура. тоже самое по выходу.
2.по Thread.Free скажу, что я пользуюсь обычно thread.terminate. в onexecute первой строчкой прописываю FreeOnTerminate=true:
procedure TMyThread.Execute;
begin
freeonterminate:=true;
while not terminated do
begin
...
end;
end;
и у меня никогда ничего не висло при этом. а вообще, если потоки убиваешь только по выходу из приложения, а так они у тебя все время работы проги живут, то забей на ручное разрушение потоков- windows сама их прикроет как надо.
3. по createsuspend- если вызываешь thread.create с createsuspend=false, то нить стартует немедленно, иначе тебе надо ручками запускать нить на выполнение.
Здравствуйте, YuRock, Вы писали:
YR>Вначале я написал экзешник (для тестов, да и отлаживать exe удобнее, чем dll) — в потоке опрашиваю Com-порт, ну и, кое-что делаю. Когда полностью отладился, все заработало — решил перенести функциональность в dll.
А на зачем?
YR>И тут началось самое интересное! В dll я сделал отдельный модуль, который выглядит примерно так:
..
http://www.pergolesi.demon.co.uk/prog/threads/ToC.html
YR>Кстати, мастера, объясните, как работает параметр CreateSuspended в TThread.Create, если в BeginThread все равно передается CREATE_SUSPENDED, даже если CreateSuspended=False:
procedure TThread.AfterConstruction;
begin
if not FCreateSuspended then
Resume;
end;
Здравствуйте, YuRock, Вы писали:
YR>Здравствуйте, s.ts, Вы писали:
ST>>а почему должно запускаться-то ? ST>>это ведь dll, а не bpl
YR>А что, есть какая-то принципиальная разница?
Здравствуйте, YuRock, Вы писали:
YR>Доброго всем дня! Вот нужно мне написать плугин, который работает с железякой ч-з Com-порт. YR>Вначале я написал экзешник (для тестов, да и отлаживать exe удобнее, чем dll) — в потоке опрашиваю Com-порт, ну и, кое-что делаю. Когда полностью отладился, все заработало — решил перенести функциональность в dll.
YR>И тут началось самое интересное! В dll я сделал отдельный модуль, который выглядит примерно так:
[skip]
С моей колокольни это видится так:
1. Создаёшь нужный тебе объект, потом в DLL описываешь функцию
function ThreadFunc(s: Pointer):DWORD;stdcall;
var
[skip]
begin
[skip]
ExitThread(0);
end;
далее делаешь ещё одну, вида
function RunProc : Cardinal;
result := CreateThread(nil,512,@ThreadFunc,Self,0,ThreadId);
// возвращаемое значение result лучше сохранить,
// т.к. если вдруг нужно будет эктсненно прибить этот трид, нужно будет знать его IDend;
вот собственно и всё, и не надо возиться с делфёвым тридом, имхо, если потоки "из DLL" (если можно так выразиться) плодить, то лучше воспользоваться WinAPI. Единственное, придётся повозиться с тем, что бы корректно эти потоки прибивать, когда выходишь из проги, когда процесс ещё выполняется. Для этого пригодится
var
result : DWORD;
begin
TerminateThread(ThreadLink, result); // ThreadLink - это то, что вернуло RunProc
ThreadLink := 0;
ну и если потоку надо общаться, то можно всё это оформить сообщениями Windows или накидать простенькие COM интерфейсы.