Текущий архив: 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.48 MB
Время: 0.044 c