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

Вниз

Обращение к ф-цииDLL одновременно из нескольких процессов   Найти похожие ветки 

 
Alex_C ©   (2007-06-13 18:54) [0]

Есть DLL, в ней есть ф-ция, в качестве аргумента принемающая некою структуру и заполняющая ее в зависимости от того, какие поля были заполнены.
В приложении несколько TTreads, которые обращаются к ф-ции данной DLL (DLL статический вызов).
Естественно, когда одновременно 2 TThread обращаются к данной ф-ции возникает ошибка. Как этого избежать?
Пробовал в DLL в  функцию ставил TRTLCriticalSection - не помогает, ведь входная структура портится, если в это время опять идет обращение к этой ф-ции.
Какие еще есть варианты?


 
Правильный Вася   (2007-06-13 19:10) [1]

ThreadSafe=True
глобальные переменные?
?


 
DrPass ©   (2007-06-13 22:50) [2]


> ведь входная структура портится, если в это время опять
> идет обращение к этой ф-ции

Каким образом она портится? Если ты создаешь один экземпляр этой структуры в динамической памяти, и в обоих потоках передаешь на него указатель, тогда да - попортится. В остальных случаях ничего с ней не произойдет, у каждого потока свой личный стек. Есть куча других, более простых способов запороть многопоточную работу, нежели порча входных параметров...


 
Правильный Вася   (2007-06-13 23:04) [3]

сорри, в секции инициализации DLL
 IsMultiThread := True;


 
Eraser ©   (2007-06-13 23:39) [4]

> [0] Alex_C ©   (13.06.07 18:54)


> Обращение к ф-цииDLL одновременно из нескольких процессов

необходимо защитить функцию объектом ядра, к примеру, мьютексом. В рамках одного приложения можно использовать критические секции.


 
Сергей М. ©   (2007-06-14 08:22) [5]


> Eraser ©   (13.06.07 23:39) [4]


> необходимо защитить функцию


Защищают не функцию, а ресурсы.
В случае автора таким ресурсом, вероятно, являются те самые структурированные данные, передаваемые фактическим параметром при вызове функции.


 
Alex_C ©   (2007-06-14 08:26) [6]

Ребята большое спасибо за советы!
Еще такой вопрос:
есть ф-ция (причем как я пинимаю не важно - в DLL она или просто в теле проги)

Func( A: String ):Integer;
begin
    EnterCriticalSection...

Вопрос:
при вызове ее одновременно допустим из 3-х Thred"ов, они дойдут до CriticalSection и будут ждать, пока можно будет идти дальше, тут понятно. А переменная А для каждых вызовов своя будет? Т.е. стек отдельный для каждого вызова и портится он не будет?


 
Alex_C ©   (2007-06-14 08:29) [7]

Да и еще в добавок: если ф-ция находится в DLL, то надо использовать уже не CriticalSection, а Мютексы?


 
Сергей М. ©   (2007-06-14 08:40) [8]


> переменная А для каждых вызовов своя будет?


Да, своя.
Только это не переменная, а параметр (аргумент) функции.


> стек отдельный для каждого вызова и портится он не будет?


Стек отдельный для каждого потока, а не для каждого вызова.
В дан.случае стек при передаче параметра вообще не испольщуется - параметр передается в регистре eax процессора.


> если ф-ция находится в DLL, то надо использовать уже не
> CriticalSection, а Мютексы?


Мьютексы как правило используются для защиты ресурсов при обращении к ним со стороны потоков разных процессов. Если функция в твоей dll планируется к одновременному использованию со стороны более чем одного процесса, то мьютекс в этом случае будет уместен, иначе достаточно крит.секции.
Крит.секции обладают ощутимым преимуществом с т.з. комплексной производительности приложений, их использующих. Но крит.секции не могут быть использованы для защиты ресурсов в условиях доступа к ним из разных процессов.


 
Alex_C ©   (2007-06-14 09:33) [9]

То Сергей М. : большое спасибо за столь подробный и понятный ответ!
Тут все ясно - все заработало как надо!
И еще вопрос:
можно ведь обойтись и без CriticalSection, с помощью глобальной переменной вот так:

While WaitWhileEnd do
   Application.ProcessMessage;
ну и далее
  WaitWhileEnd := True;
  // текст проги
  WaitWhileEnd := False;

Чем плох такой метод?


 
Loginov Dmitry ©   (2007-06-14 10:58) [10]

> можно ведь обойтись и без CriticalSection, с помощью глобальной
> переменной вот так:
>
> While WaitWhileEnd do
>   Application.ProcessMessage;
> ну и далее
>  WaitWhileEnd := True;
>  // текст проги
>  WaitWhileEnd := False;


и что даст Application.ProcessMessage? Только дополнительные грабли, особенно, если данный код начнет вызываться из дополнительных потоков. Чуть надежнее будет, если вместо него вставить, скажем, Sleep(50) - меньше нагрузки на процессор, но и это отвратительный выход, так как цикл ожидания запросто может одновременно завержиться у двух потоков и они одновременно перейдут к выполнинию "текста проги". Единственный надежный способ защиты ресурсов - использование критической секции либо объектов синхронизации.


 
Сергей М. ©   (2007-06-14 11:28) [11]


> Чем плох такой метод?


Тем что его использование рано или поздно приведет к успешной попытке захвата защищаемого ресурса более чем одним потоком - между строчками

While WaitWhileEnd do

и

WaitWhileEnd := True;

запросто может произойти переключение контекста потоков



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

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

Наверх




Память: 0.5 MB
Время: 0.025 c
8-1163533089
PAN
2006-11-14 22:38
2007.08.26
Быстрая последовательная загрузка и показ изображений


2-1185987668
XL007
2007-08-01 21:01
2007.08.26
Cgi под windows


8-1164108426
Igor_thief
2006-11-21 14:27
2007.08.26
GIF через OLE


15-1185349224
ПЛОВ
2007-07-25 11:40
2007.08.26
SQL


2-1186296860
Константинов
2007-08-05 10:54
2007.08.26
SQL запрос