![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Обращение к ф-цииDLL одновременно из нескольких процессов [D7, WinXP]
Alex_C © (2007-06-13 18:54:00)Есть DLL, в ней есть ф-ция, в качестве аргумента принемающая некою структуру и заполняющая ее в зависимости от того, какие поля были заполнены.
В приложении несколько TTreads, которые обращаются к ф-ции данной DLL (DLL статический вызов).
Естественно, когда одновременно 2 TThread обращаются к данной ф-ции возникает ошибка. Как этого избежать?
Пробовал в DLL в функцию ставил TRTLCriticalSection - не помогает, ведь входная структура портится, если в это время опять идет обращение к этой ф-ции.
Какие еще есть варианты?
Сергей М. (2007-06-14 11:28:00) [1]
> Чем плох такой метод?
Тем что его использование рано или поздно приведет к успешной попытке захвата защищаемого ресурса более чем одним потоком - между строчками
While WaitWhileEnd do
и
WaitWhileEnd := True;
запросто может произойти переключение контекста потоков
Loginov Dmitry (2007-06-14 10:58:00) [2]> можно ведь обойтись и без CriticalSection, с помощью глобальной
> переменной вот так:
>
> While WaitWhileEnd do
> Application.ProcessMessage;
> ну и далее
> WaitWhileEnd := True;
> // текст проги
> WaitWhileEnd := False;
и что даст Application.ProcessMessage? Только дополнительные грабли, особенно, если данный код начнет вызываться из дополнительных потоков. Чуть надежнее будет, если вместо него вставить, скажем, Sleep(50) - меньше нагрузки на процессор, но и это отвратительный выход, так как цикл ожидания запросто может одновременно завержиться у двух потоков и они одновременно перейдут к выполнинию "текста проги". Единственный надежный способ защиты ресурсов - использование критической секции либо объектов синхронизации.
Alex_C (2007-06-14 09:33:00) [3]То Сергей М. : большое спасибо за столь подробный и понятный ответ!
Тут все ясно - все заработало как надо!
И еще вопрос:
можно ведь обойтись и без CriticalSection, с помощью глобальной переменной вот так:
While WaitWhileEnd do
Application.ProcessMessage;
ну и далее
WaitWhileEnd := True;
// текст проги
WaitWhileEnd := False;
Чем плох такой метод?
Сергей М. (2007-06-14 08:40:00) [4]
> переменная А для каждых вызовов своя будет?
Да, своя.
Только это не переменная, а параметр (аргумент) функции.
> стек отдельный для каждого вызова и портится он не будет?
Стек отдельный для каждого потока, а не для каждого вызова.
В дан.случае стек при передаче параметра вообще не испольщуется - параметр передается в регистре eax процессора.
> если ф-ция находится в DLL, то надо использовать уже не
> CriticalSection, а Мютексы?
Мьютексы как правило используются для защиты ресурсов при обращении к ним со стороны потоков разныхпроцессов. Если функция в твоей dll планируется к одновременному использованию со стороны более чем одного процесса, то мьютекс в этом случае будет уместен, иначе достаточно крит.секции.
Крит.секции обладают ощутимым преимуществом с т.з. комплексной производительности приложений, их использующих. Но крит.секции не могут быть использованы для защиты ресурсов в условиях доступа к ним из разных процессов.
Alex_C (2007-06-14 08:29:00) [5]Да и еще в добавок: если ф-ция находится в DLL, то надо использовать уже не CriticalSection, а Мютексы?
Alex_C (2007-06-14 08:26:00) [6]Ребята большое спасибо за советы!
Еще такой вопрос:
есть ф-ция (причем как я пинимаю не важно - в DLL она или просто в теле проги)
Func( A: String ):Integer;
begin
EnterCriticalSection...
Вопрос:
при вызове ее одновременно допустим из 3-х Thred'ов, они дойдут до CriticalSection и будут ждать, пока можно будет идти дальше, тут понятно. А переменная А для каждых вызовов своя будет? Т.е. стек отдельный для каждого вызова и портится он не будет?
Сергей М. (2007-06-14 08:22:00) [7]
> Eraser © (13.06.07 23:39) [4]
> необходимо защитить функцию
Защищают не функцию, а ресурсы.
В случае автора таким ресурсом, вероятно, являются те самые структурированные данные, передаваемые фактическим параметром при вызове функции.
Eraser (2007-06-13 23:39:00) [8]> [0] Alex_C © (13.06.07 18:54)
> Обращение к ф-цииDLL одновременно из нескольких процессов
необходимо защитить функцию объектом ядра, к примеру, мьютексом. В рамках одного приложения можно использовать критические секции.
Правильный Вася (2007-06-13 23:04:00) [9]сорри, в секции инициализации DLL
IsMultiThread := True;
DrPass (2007-06-13 22:50:00) [10]
> ведь входная структура портится, если в это время опять
> идет обращение к этой ф-ции
Каким образом она портится? Если ты создаешь один экземпляр этой структуры в динамической памяти, и в обоих потоках передаешь на него указатель, тогда да - попортится. В остальных случаях ничего с ней не произойдет, у каждого потока свой личный стек. Есть куча других, более простых способов запороть многопоточную работу, нежели порча входных параметров...
Правильный Вася (2007-06-13 19:10:00) [11]ThreadSafe=True
глобальные переменные?
?