Форум: "Основная";
Текущий архив: 2006.11.19;
Скачать: [xml.tar.bz2];
Вниз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;//nilfunction 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;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.042 c