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

Вниз

DLL и TThread s   Найти похожие ветки 

 
MetalFan ©   (2006-10-10 13:55) [0]

вопросы по сабжу:
как правильно работать с DLL из потока?
1) будет ли для каждой загруженной в отдельный поток dll отдельное АП? или все переменные, используемые в длл будут одинаковыми для каждой библиотеки в разных потоках.
2) можно ли использовать callback процедуры в длл, объявленные как procedure of object? если да, то как не напороться на "подводные камни"?

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

в общем буду рад всем ответам/советам.
с ув, MetalFan


 
Leonid Troyanovsky ©   (2006-10-10 14:27) [1]


> MetalFan ©   (10.10.06 13:55)  

> 1) будет ли для каждой загруженной в отдельный поток dll
> отдельное АП? или все переменные, используемые в длл будут
> одинаковыми для каждой библиотеки в разных потоках.

Библиотека работает в адресном пространстве процесса-хоста.
Все глобальные переменные едины для всех потоков.

> 2) можно ли использовать callback процедуры в длл, объявленные
> как procedure of object? если да, то как не напороться на

Нельзя.
Проще всего, вообще, забыть про ООП в длл.

--
Regards, LVT.


 
Сергей М. ©   (2006-10-10 14:40) [2]


> как не напороться на "подводные камни"?


Шансов "напороться" немало.

Приводи конкретный код - будет и вердикт ..


 
MetalFan ©   (2006-10-10 14:54) [3]

мда... придется поизваращаться тогда)
Leonid Troyanovsky, огромное спасибо за ответ!!!


 
han_malign ©   (2006-10-10 14:56) [4]

1)или
"глобальная" для DLL переменная объявленная в секции threadvar - будет для каждого потока своя - но тут много подводных камней с (де)инициализацией(см. ниже)...
2)можно, т.к. of object - просто обозначет неявную передачу контекста(self)

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

- если в DLL существует какой то "внутренний глобальный" контекст, то нужно выделить под него память(получить из DLL, или выделить в потоке и передать в DLL), все обращения к DLL производить с указанием этого контекста, не забыть "отпустить" память контекста... если контекст "активный" объект - его надо создавать в контексте DLL, методами в основном приложении лучше не пользоваться(если нет представления о том что такое "абстрактный интерфейс/класс").
Если используется threadvar контекст выделяется автоматически в TLS потока, но использование там динамических объектов - задача требующая навыка, т.к. встренных(на уровне Delphi-абстракции) нотификаций на инициализацию/деинициализацию нет -
надо либо явно делать в Thread.Execute==><DLL-Init-Context/DLL-Release-Context, либо ловить DLL_THREAD_ATTACH/DLL_THREAD_DETACH перекрывая System.DLLProc.
Хотя, в общем, порядок действий такой же как и в случае ручного создания контекста. Единственное преимущество в использовании threadvar - что не нужно указывать/искать контекст в зависимости от вызывающего потока...

З.Ы. Самое главное - не забывать IsMultiThread:= true; в DLL - иначе долго будешь ловить AV в, казалось бы, тривиальных местах... Например Get/FreeMem или longStr:= "Hello World!"....


 
MetalFan ©   (2006-10-10 15:00) [5]

тогда вопрос в следующем: как добиться того, чтобы для каждого потока в длл были свои переменные?
возможен ли вариант с DLLEntryPoint.
или сделать функцию инициализации, которая будет создавать некий объект с идентификатором и отавать этот id обратно потоку...
в общем какие еще возможны варианты?
заранее спасибо!


 
MetalFan ©   (2006-10-10 15:18) [6]


> han_malign ©   (10.10.06 14:56) [4]

спасибо!

собстно еще вопрос, точнее ситуация:

Поток1.execute
 ll:=LoadLibrary(..);
 @lproc:=GetProcAddres(..);
 if assigned(@lProc) then
  lProc(..);
-----
в это же время
Поток2.execute
 ll:=LoadLibrary(..);
 @lproc:=GetProcAddres(..);
 if assigned(@lProc) then
  lProc(..);

как разрулить данные внутри длл. или вызов из "поток2" произойдет только после вызова из первого?


 
han_malign ©   (2006-10-10 15:28) [7]


> будет создавать некий объект с идентификатором и отавать этот id обратно потоку...

- обычно в качестве ID используют указатель на экземпляр, в этом случае не нужно городить списков с поиском... Существует конечно вероятность попытки работать с неправильным контекстом, при которой все закончится моментальным крахом(т.к. нельзя(трудно) проверить валидность контекста), но если всегда четко отрабатывать "контекстные" скобки:
TMyThread.Execute;
var ctx: DWORD;
begin
    if(LoadLib)then begin
         ctx:= myDllCreateContext;
         if(ctx <> my_dll_invalid_context)then begin
             while not Terminate do myDllLoop(ctx);
             myDllReleaseContext(ctx);
         end;
         UnloadLib;
    end;
end;
- подобных проблем быть не должно.
Это вариант с явной инициализацией контекста, без всяких извращений с DLLEntryPoint.
естественно в DLL:
my_dll_invalid_context = 0;//nil
function myDllCreateContext: DWORD;
begin
    try
         Result:= DWORD(TMyDllProcess.Create);
    except//на тот случай если не хватит ресурсов
         Result:= 0;
    end;
end;

procedure myDllReleaseContext(ctx: DWORD);
begin
    TMyDllProcess(ctx).Free;
end;

procedure myDllLoop(ctx: DWORD);
begin
    TMyDllProcess(ctx).DoLoop;
end;
export
     myDllCreateContext,
     myDllReleaseContext,
     myDllLoop;
begin
  IsMultiThread:= true;
end.


 
han_malign ©   (2006-10-10 15:34) [8]


> как разрулить данные внутри длл. или вызов из "поток2" произойдет только после вызова из первого?

- они могут произойти обновременно, но - LoadLibrary, GetProcAddres - потокобезопасные(на совести ядра), и в пердыдущем примере - функции DLL также являются потокобезопасными...


 
MetalFan ©   (2006-10-10 15:34) [9]


> han_malign ©   (10.10.06 15:28) [7]

то, что надо! спасибо!
а как из DLL "дернуть" методы потока? и/или осуществить обмен некоторыми данными? что-то типа PostThreadMessage?
как в потоке узнать, что длл от него что-то хочет?


 
han_malign ©   (2006-10-10 15:42) [10]


> как в потоке узнать, что длл от него что-то хочет?

type TAppCalback = procedure(aAppContext: DWORD; aDllData: TMyDllData);

function myDllCreateContext(aAppContext: DWORD; aAppCallback: TAppCalback): DWORD;


 
MetalFan ©   (2006-10-10 15:55) [11]


> han_malign ©   (10.10.06 15:42) [10]

ага... и пройтись по списку потоков и найти нужный с AppContext?!
я правильно понял?
все, тогда огромное спасибо! буду программить!!!


 
han_malign ©   (2006-10-10 18:18) [12]


> ага... и пройтись по списку потоков и найти нужный с AppContext?!

function myDllCreateContext(aAppContext: DWORD; aAppCallback: TAppCalback): DWORD;
begin
   try
        Result:= DWORD(TMyDllProcess.Create(aAppContex, aAppCallback));
   except
        Result:= 0;
   end;
end;

- для чего ты спрашивается контекст создаешь?


 
MetalFan ©   (2006-10-10 19:26) [13]


> han_malign ©   (10.10.06 18:18) [12]

точно, сорь, туплю)
т.о. длл "знает" о thread"ах, что ее пользуют, а thread"ы "знают" свой контекст в dll...
классный подход! спасибо за идею!


 
Leonid Troyanovsky ©   (2006-10-10 20:23) [14]


> MetalFan ©   (10.10.06 15:00) [5]

> тогда вопрос в следующем: как добиться того, чтобы для каждого
> потока в длл были свои переменные?


RTFM: msdn TlsAlloc & etc
See also: threadvar (Delphi)

--
Regards, LVT.


 
Vovan#1   (2006-10-10 21:01) [15]

Автору.

Uploader делаешь? Благое дело.


 
MetalFan ©   (2006-10-11 12:53) [16]


> Vovan#1   (10.10.06 21:01) [15]

откуда знаешь? ))


 
Vovan#1   (2006-10-11 21:00) [17]

> откуда знаешь? ))

По коду вижу. Зачем же ещё потоки в DLL?


 
OldNaum ©   (2006-10-11 21:25) [18]

тот самый MetalFan c нонейма? благое дело =)


 
MetalFan ©   (2006-10-11 21:48) [19]


> OldNaum


тот самый ;)


> Vovan#1   (11.10.06 21:00) [17]
>
> > откуда знаешь? ))
>
> По коду вижу. Зачем же ещё потоки в DLL?

наоборот) ДЛЛ в потоках)



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

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

Наверх




Память: 0.52 MB
Время: 0.175 c
2-1162472501
Fulkon
2006-11-02 16:01
2006.11.19
Как нажимать на кнопки и заполнять формы чужих инсталяторов!!


2-1162374315
dmdel
2006-11-01 12:45
2006.11.19
Округление чисел


11-1138876248
Dodfr
2006-02-02 13:30
2006.11.19
Problem ListBox.OnDrawItem


3-1158810978
Merko2005
2006-09-21 07:56
2006.11.19
Как вычислить кол-во месяцев


2-1162308816
doooooo
2006-10-31 18:33
2006.11.19
DWord => 2Word