Форум: "Базы";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.02.14;
Скачать: [xml.tar.bz2];




Вниз

нити (threads) и базы данных (MSAccess) 


ShaH   (2002-01-17 10:08) [0]

программа многопоточная и работает с базой данных (MSAccess). При попытке записи данных в базу (выборка работает нормально) из нити (thread)происходит Access Violation из модуля DAO350.dll если данные пишутся не из нити (thread) то все проходит нормально. В чем дело ? Помогите, голову уже поломал.



roottim   (2002-01-17 10:29) [1]

может быть дело в том что 2 потока пытаются обратиться к базе одновременно...
к примеру, как 2 клиента подсоединяются к БД не поддержиающей сетевые технологии...



ShaH   (2002-01-17 10:49) [2]

БД - MSAccess открывается неэксклюзивно, при попытке доступа из 2-х или более мест к обной записи должно появляться сообщение "Record Lock by Another User" или что-то в этом духе. Я не прав ?



roottim   (2002-01-17 11:18) [3]

все верно!... но в этом сл... помоему работают 2 сессии...
а потоки через одну... хм... довольно сложно так разобраться



Digitman   (2002-01-17 12:27) [4]

объект DAO.DBEngine имеет атрибут ThreadingModel = Apartment. Это означает, что доступ к методам/св-вам такого объекта может иметь только лишь тот поток, который создал сам объект.
Ни одна фабрика какого-либо класса, реализующая модель Apartment, не позволяет создавать экз-р объекта в одном потоке, а использовать созданный объект - в другом. Фабрика класса DAO.DBEngine (т.е. фабрика, реализованная в библ-ке DAOXX.DLL, вплоть до версии 4.0) не является исключением.



kig   (2002-01-17 15:34) [5]

2Digitman

>Ни одна фабрика какого-либо класса, реализующая модель Apartment, не позволяет создавать экз-р объекта в одном потоке, а использовать созданный объект - в другом.

Ну зачем так категорично утверждать, что нельзя пользовать в разных потоках и так народ то пугать? :))

Другое дело, что для того, что бы можно было использовать, необходимо проделать ряд манипуляций. И не факт, что в данном случае эти манипуляции лучшее решение, чем создание второго экземпляра DAO во втором потоке. Но все-таки так категорично утвержлать, что нельзя, это не есть правильно...



Digitman   (2002-01-17 15:55) [6]

>kig
Возражаешь ? Аргументируй !! Всякие API-"примочки" для синхронизации маршаллера с нужным потоком не рассматриваю. Докажи, что для кабинетных моделей можно создать объект в одном потоке, а обращаться к нему - в другом. Только тогда я сниму шляпу ).



kig   (2002-01-17 16:04) [7]

2Digitman

"Всякие API-"примочки" для синхронизации маршаллера с нужным потоком не рассматриваю" - а это как понять? :)
Может тогда не рассматривать всякие "примочки" типа CoCreateInstance и вообще все, которые CoXXXX...., OleXXX ...? Может тогда вообще речь не о COM"е идет? :))

Так мы рассматриваем ВСЕ "примочки" COM-API или нет? :))



ShaH   (2002-01-17 16:31) [8]

to kig & Digitman

самое интересное, что описанная мною ранее проблема возникла не сразу, а какое-то время успешно работала. Потом в какой-то момент начали валиться Access Violation"ы . Проблему вроде решил (пока) в нити вызываются TQuery.ExecSql(), при этом TTable для этой базы данных не открываются. Все работает.



Digitman   (2002-01-17 16:45) [9]

>kig
Нет, не рассматриваем. И упомянутая тобой "примочка" CoCreateInstance вовсе к примочкам не относится, т.к. сей вызов собственно и создает экз-р объекта. И именно в том потоке, в котором вызов происходит, и должно впоследствии обращаться к объекту. Если же ты используешь "примочки", то, разумеется, они будут реализовывать этот "мост" : вызываешь "примочку" из произвольного потока, а она синхронизирует интерфейсный вызов с потоком, реально создавшим объект.
Реализуй какой-нибудь свой Apartment-объект, поставь в конструктор и обработчик какого-либо его метода вызов GetCurrentThread, затем проделай то, о чем говорим, с использованием "примочек" и сравни идентификаторы потоков, читаемые в коде конструктора и метода. Тогда и шляпы снимать будем)



roottim   (2002-01-17 17:15) [10]

QReport тоже создает отдельный поток на Preview... и работает через один экземпляр соединения...
тут как быть?



kig   (2002-01-17 18:36) [11]

2roottim

Если Вас продолжает интересовать этот вопрос, то посмотрите следующее:

For more information about creating multi-threaded applications using DAO 3.5, read the section "DAO and the Apartment-threading Model" in DAO SDK 3.5 online documentation.

Keywords : kbcode kbDAO kbDatabase kbMFC kbVC kbVC500 kbVC600
Issue type : kbprb
Technology : kbvc


2Digitman

Вы меня хотите убедить в том, что вызов будет проходить в ните, создавшей объект? Не надо :) Я это давно знаю :) В этом то и
заключается вся соль синхронизации, которую предоставляет COM
при синхронизации доступа к не Free-объектам из разных нитей. Не нравится синхронизация, пердоставляемая COM? Пишете Free-объекты и синхронизуйтесь сами... Кстати, приведенным примером Вы сами опровергли категоричное утверждение "Ни одна фабрика какого-либо класса, реализующая модель Apartment, не позволяет создавать экз-р объекта в одном потоке, а использовать созданный объект - в другом." :)

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



ShaH   (2002-01-17 21:01) [12]

есть еще вопросы :
1. Почему ошибка не проявилась сразу
2. Почему ошибка не возникала при Select, а только при Append или Insert
3. Когда происходит создание объекта DAO.DBEngine при установке TDataBase.Connected:=true ? или когда ?

И как выкручиваться, что создавать отдельную нить для работы с базой данных ? Помогите, сроки горят, а голова уже, видимо не варит.



kig   (2002-01-17 21:47) [13]

2ShaH

Дело в том, что у меня не стоит DAO SDK (knowledge base из MSDN как раз туда и посылает - выдержку оттуда я привел выше) да и с DAO напрямую я давно не работаю - для этого есть ADO.

Если сроки горят, попробуйте из отдельной нити просто открывать отдельный коннект к БД и работать через него. А так разбираться с DAO SDK.



Digitman   (2002-01-18 09:52) [14]

>kig
Убеждать тебя ни в чем не собираюсь. Оно мне надо ? А вот что касаемо конкретной проблемы автора, то ему важно понять, что для устранения проблемы без излишних "выкрутасов" (о коих ты речь завел) ему нужно, чтобы каждый поток имел свой собственный экз-р DAO.DBEngine и работал только со своим собственным, не затрагивая экземпляры, созданные в других потоках



ShaH   (2002-01-18 14:51) [15]

to Digitman
>> чтобы каждый поток имел свой собственный экз-р DAO.DBEngine
>> и работал только со своим собственным, не затрагивая
>> экземпляры, созданные в других потоках

это я уже понял , я и спрашивал уже когда создаются эти экземпляры ? когда я пишу TDataBase.Connected=true или когда ???

я этого понять не могу !!!!!!



Digitman   (2002-01-18 15:10) [16]

да. именно в момент TDataBase.Connected:=true
но !! экземпляр TDataBase тоже должен быть создан в том же потоке, где и TDataBase.Connected:=true



ShaH   (2002-01-18 15:26) [17]

ясно, давайте тогда разберемся до конца.

1. ясно почему не должно было работать, когда TDataBase открывался вне нити в которой использовался, но TQuery с select"ом работали. ПОЧЕМУ ?
2. сейчас все нити используют один закрытый TDataBase лежащий на DataModule и все прекрасно работает, т.е. каждая нить его (TDatBase) открывает и закрывает. Нового экземпляра не создается. Это случайность ? Или в каждую нить передаются новые объекты из подключаемых юнитов ?



Digitman   (2002-01-18 15:47) [18]

нити используют у тебя экз-р объекта TDatabase по очереди, по этому конфликтов на уровне использования DAO.DBEngine не возникает. Но два разных TQuery, созданных в разных нитях и ссылающихся на общий TDatabase смогут работать одновременно:

созданный экз-р DAO.DBEngine при выполнении одной из нитей команды TDatabase.Connected:= True будет ассоциирован именно с этой нитью (TDatabase.Connected:= True неявно вызывается при выполнении TQuery.Active:= True), и другая нить, тоже выполняющая свой собственный TQuery.Active:= True, будет пытаться использовать тот же экз-р активного в этот момент TDatabase для доступа к DAO.DBEngine и вот тут-то и произойдет казус !!




Форум: "Базы";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.02.14;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.76 MB
Время: 0.018 c
1-42771           IronHawk              2002-01-31 12:57  2002.02.14  
Уважаемые Мастера! Опять нужна ваша помощ с fsMDIChild.


7-42881           Al Creator            2001-11-07 22:52  2002.02.14  
Как получить разрешение экрана?


1-42746           UserL                 2002-01-29 08:27  2002.02.14  
Помогите, плиз...


6-42819           _Voodsboro_           2001-11-25 13:55  2002.02.14  
NMSMTP/ КАК написать анонимный маил


14-42831          lel                   2001-12-24 12:48  2002.02.14  
Где в Москве выпить?