Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

ADO в потоках [D7, Access]


Vilux ©   (2004-11-23 13:28:00) 

В потоке пускаю dll, которая подключается к аксессовской базе и выполняет запрос. Но если создать много потоков, то все "падает". Если убрать процедуру подключения к базе, то все работает нормально. Пробовал в этой dll использовать CoInitialize(nil) и  CoUnInitialize, но не помогает...:( какие еще мысли и советы есть?


Digitman   (2004-11-23 15:33:00) [1]


> Vilux ©   (23.11.04 15:05) [16]
> ну и как


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


sniknik   (2004-11-23 15:30:00) [2]

когда делаеш dll новую оно прямо в начале комментарием вставляется.


Vilux   (2004-11-23 15:11:00) [3]

sniknik, какое предупреждение и где его можно прочитать?


Vilux   (2004-11-23 15:05:00) [4]

2Digitman, ну и как мне поможет отладчик при отладке потоков?
И я не спорю, что все понимаю, по-крайней мере пытаюсь найти ответы на этом форуме.


sniknik   (2004-11-23 15:04:00) [5]

> result пока убрал...все равно вылетает.
зачем? тогда убирай все что со строками работает, иначе смысла нет. (или всетаки прочитать предупреэжение)


Digitman   (2004-11-23 14:59:00) [6]

пробовал так, пробовал сяк ...

прямо-таки - басня Крылова про мартышку и очко.

галиматья.
при полном непонимании.

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


Vilux   (2004-11-23 14:49:00) [7]

да, вот, сразу надо было написать

function GetHelp:string;
var ado:TAdoConnection;
q:TAdoQuery;
begin
---то что выше
end;
т.е. переменные локальные.
Попробовал сейчас один раз только грузить dll и передавать адрес процедуры в каждый поток. result пока убрал...все равно вылетает. Причем просто исчезает процесс, без всяких мессаг. Был и не стало.


sniknik   (2004-11-23 14:41:00) [8]

> Только вот не понял, почему же в таком случае программы вылетает.
ado, q переменные локальные или глобальные?

result:=q.fieldbyname('HelpF'). AsString;
при создании dll внимательно предупреждение читал, которое там выдается?

и т.д. глюк как всегда в другом. ;о))


Vilux   (2004-11-23 14:36:00) [9]

Ведь каждый раз при вызове указанной выше процедуры создается новый ADOConnection  и т.п. Почему криво работает...


Vilux   (2004-11-23 14:35:00) [10]

:( ладно...более-менее разобрался. Только вот не понял, почему же в таком случае программы вылетает.Учитывая то, что если убрать работу с БД, то все работает


Digitman   (2004-11-23 14:30:00) [11]


> если из кучи потоков обращаться одноверменно к функции,
> которая расположена под одному и тому же адресу


с какого перепугу адрес ф-ции изменится-то ?

try
CoInitialize(nil);
ado:=TADOConnection.Create(nil);
ado.ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;Data Source='+sc_base+';Persist Security Info=False';
ado.LoginPrompt:=false;
ado.Open;
q:=TAdoQuery.create(nil);
q.Connection:=ado;
q.SQL.Text:=format(
'select HelpF from TKey where Page=''%s'''
,[page]);
q.Open;
result:='';
if q.RecordCount>0 then
result:=q.fieldbyname('HelpF').AsString;
q.Close;
q.free;
ado.Close;
ado.Free;
CoUninitialize;
except
log('Error in GetHelp function');
end;


> косяки пойдут? или я не прав?


ты не прав, называя "косяками" то чего не понимаешь.
никаких "косяков" нет и быть не может.


> как мне сделать, чтобы в каждом потоке существовала своя
> функция?


галиматья.
функция - это в конечном итоге фрагмент машкода.
этот самый фрагмент машкода начинает фигурировать в АП процесса при ПЕРВОМ же успешном результате явного/неявного выполнения LoadLibrary(), неважно в контексте какого трэда сделанного.


Vilux   (2004-11-23 14:29:00) [12]

Так я не понял, конфликты идут от того, что все потоки пытаются обратиться к одной и той же функции по одному адресу? Так?


KSergey   (2004-11-23 14:24:00) [13]

> [6] Vilux ©   (23.11.04 14:19)
> так как мне быть то? ведь если из кучи потоков обращаться
> одноверменно к функции, которая расположена под одному и
> тому же адресу, тогда ведь косяки пойдут? или я не прав?
> как мне сделать, чтобы в каждом потоке существовала своя
> функция

Не прав. Каждая функция существует в каждой программе один единственный раз по определению.


Vilux   (2004-11-23 14:19:00) [14]

так как мне быть то? ведь если из кучи потоков обращаться одноверменно к функции, которая расположена под одному и тому же адресу, тогда ведь косяки пойдут? или я не прав? как мне сделать, чтобы в каждом потоке существовала своя функция?


Digitman   (2004-11-23 14:14:00) [15]

DLL грузится в АП процесса лишь при первом успешном обращении к LoadLibrary(), неважно из какого трэда сделланном.

при всех последующих обращениях к LoadLibrary() для той же DLL лишь увеличивается на 1-цу сч-к ссылок на эту библ-ку, а сама загрузка не происходит - образ модуля и так уже находится в АП процесса

при каждом FreeLibrary() для этой DLL (неважно из какого треда произошел этот вызов) на 1-цу уменьшается сч-к ссылок на эту библ-ку, и библиотека будет выгружена системой, как только сч-к станет равен 0.


> Если убрать процедуру подключения к базе, то все работает
> нормально


как же твой запрос выполнится, если "убрать процедуру подключения" ?


Vilux   (2004-11-23 13:58:00) [16]

1.Поподробнее...
в цикле создается, допустим, 100 потоков...
в каждом потоке в память подгружается dll-ка и вызывается функция из нее, которая работает с базой...вот и все
2.Если я в самом начале подгружу dll-ку, и буду в каждом потоке вызывать ее функцию, то как раз получится, что мне придется делать это по очереди. Тогда пропадает весь смысл многопоточности. А если в каждом потоке подгружается dll-ка, то по идее все должно работать, но на практике не работает :(


KSergey   (2004-11-23 13:51:00) [17]

> [2] Vilux ©   (23.11.04 13:47)
> А вот как делаю в dll-ке

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


Vilux   (2004-11-23 13:47:00) [18]

Вот что я делаю в dll-ке... т.е. получается, что я создаю каждый раз свой коннект...другой вопрос, когда я запускаю dll-ку в потоке, то для каждого потока dll-ка отдельно грузится?В потоке я делаю так hinstDLL := LoadLibrary(pchar(dllname)); и вроде как в каждом потоке значение hinstDLL одно и то-же... так и должно быть?
А вот как делаю в dll-ке
try
CoInitialize(nil);
ado:=TADOConnection.Create(nil);
ado.ConnectionString:='Provider=Microsoft.Jet.OLEDB.4.0;Data Source='+sc_base+';Persist Security Info=False';
ado.LoginPrompt:=false;
ado.Open;
q:=TAdoQuery.create(nil);
q.Connection:=ado;
q.SQL.Text:=format(
'select HelpF from TKey where Page=''%s'''
,[page]);
q.Open;
result:='';
if q.RecordCount>0 then
 result:=q.fieldbyname('HelpF').AsString;
q.Close;
q.free;
ado.Close;
ado.Free;
CoUninitialize;
except
log('Error in GetHelp function');
end;


KSergey   (2004-11-23 13:34:00) [19]

Надо
а) Либо в каждом потоке ходить через свой коннект
б) Либо если используется 1 коннект - то запросы выполнять раздельно для каждого топока.

ADO не поддерживает потокобезопасный доступ через один коннект к базе. Либо я чего-то не знаю ;)


Наверх

Титульная страница Поиск, карта сайта Написать письмо