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

Наверх




Память: 0.5 MB
Время: 0.042 c
2-1162398499
vain
2006-11-01 19:28
2006.11.19
Перерисовка (Repaint и др.)


1-1160121293
DVM
2006-10-06 11:54
2006.11.19
Динамическое создание форм на закладках PageControl. Вопрос.


3-1158323199
BBCHa
2006-09-15 16:26
2006.11.19
Синхранизация БД с MS Outlook


6-1151431213
anton773
2006-06-27 22:00
2006.11.19
докачка файлов


15-1162051186
Chort
2006-10-28 19:59
2006.11.19
Соло на клавиатуре





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский