Потоки в "Дельфевых" библиотеках
От: YuRock Украина  
Дата: 28.04.04 10:52
Оценка:
Доброго всем дня! Вот нужно мне написать плугин, который работает с железякой ч-з 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)]);

А то что-то не понятно мне. Спасибо.
Re: Потоки в "Дельфевых" библиотеках
От: s.ts  
Дата: 28.04.04 12:08
Оценка: -2
Hello, YuRock!

Y> procedure TMyThread.Execute;

Y> begin
Y> MessageBox(0, '1', '', 0);
Y> end;

см. TThread.Synchronize
Posted via RSDN NNTP Server 1.8
Re[2]: Потоки в "Дельфевых" библиотеках
От: YuRock Украина  
Дата: 28.04.04 12:18
Оценка:
Здравствуйте, s.ts, Вы писали:

ST>Hello, YuRock!


Y>> procedure TMyThread.Execute;

Y>> begin
Y>> MessageBox(0, '1', '', 0);
Y>> end;

ST>см. TThread.Synchronize



И при чем здесь Synchronize? Не понятно... Тем более, учитывая тот факт, что Execute даже не запускается...
Re[3]: Потоки в "Дельфевых" библиотеках
От: s.ts  
Дата: 28.04.04 12:24
Оценка:
Здравствуйте, YuRock, Вы писали:

YR>Здравствуйте, s.ts, Вы писали:


ST>>Hello, YuRock!


Y>>> procedure TMyThread.Execute;

Y>>> begin
Y>>> MessageBox(0, '1', '', 0);
Y>>> end;

ST>>см. TThread.Synchronize



YR>И при чем здесь Synchronize? Не понятно... Тем более, учитывая тот факт, что Execute даже не запускается...


а почему должно запускаться-то ?
это ведь dll, а не bpl
Re[4]: Потоки в "Дельфевых" библиотеках
От: YuRock Украина  
Дата: 28.04.04 12:29
Оценка:
Здравствуйте, s.ts, Вы писали:

ST>а почему должно запускаться-то ?

ST>это ведь dll, а не bpl

А что, есть какая-то принципиальная разница?
Re: Потоки в "Дельфевых" библиотеках
От: kvl_mikki Россия  
Дата: 29.04.04 15:03
Оценка:
Добрый день!

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, то нить стартует немедленно, иначе тебе надо ручками запускать нить на выполнение.

--
Каратаев Владимир
... << RSDN@Home 1.1.0 stable >>
Re: Потоки в "Дельфевых" библиотеках
От: Leonid Troyanovsky  
Дата: 29.04.04 18:33
Оценка: +1
Здравствуйте, 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;
--
С уважением, LVT
Re[5]: Потоки в "Дельфевых" библиотеках
От: s.ts  
Дата: 30.04.04 06:28
Оценка:
Здравствуйте, YuRock, Вы писали:

YR>Здравствуйте, s.ts, Вы писали:


ST>>а почему должно запускаться-то ?

ST>>это ведь dll, а не bpl

YR>А что, есть какая-то принципиальная разница?


да и не малая
Re: Потоки в "Дельфевых" библиотеках
От: dnsokol Россия  
Дата: 04.05.04 14:39
Оценка:
Здравствуйте, 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 лучше сохранить, 
    // т.к. если вдруг нужно будет эктсненно прибить этот трид, нужно будет знать его ID
end;


вот собственно и всё, и не надо возиться с делфёвым тридом, имхо, если потоки "из DLL" (если можно так выразиться) плодить, то лучше воспользоваться WinAPI. Единственное, придётся повозиться с тем, что бы корректно эти потоки прибивать, когда выходишь из проги, когда процесс ещё выполняется. Для этого пригодится

var
  result : DWORD;
begin
    TerminateThread(ThreadLink, result); // ThreadLink - это то, что вернуло RunProc
    ThreadLink := 0;


ну и если потоку надо общаться, то можно всё это оформить сообщениями Windows или накидать простенькие COM интерфейсы.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.