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

Вниз

Про Indy и синхронизацию потоков   Найти похожие ветки 

 
NorthMan   (2005-07-01 08:07) [0]

Народ, подскажите, как лучше сделать.
Проблема такая:
Есть idTCPServer. В OnExecute принимается запрос от клиента, затем нужно выполнить внешнюю процедуру типа TForm1.GetData, в которой выполняется запрос в базу через ADO (выполняется AThread.Synchronize(TForm1.GetData)), а результат запроса необходимо вернуть в OnExecute. Подскажите, как с т.з. потока правильнее передать результат запроса. Через глобальную переменную, как мне кажется, нельзя, т.к. клиентов в каждый момент времени может быть много.


 
Slym ©   (2005-07-01 08:26) [1]

Ну и делалбы в каждом потоке свой запрос... указывая общий Конекшн
И никаких синхронизаций и подвисов всех клиентов из-за того что один запрос подвис.


 
NorthMan   (2005-07-01 11:40) [2]

беда в том, что сервер организован в виде службы, а ADO что-то не очень любит такие выкрутасы


 
Digitman ©   (2005-07-01 11:43) [3]


> сервер организован в виде службы, а ADO что-то не очень
> любит такие выкрутасы


что, прямо так и говорит, мол, не люблю и все тут ?

а при чем здесь тогда синхронизация ?


 
Slym ©   (2005-07-01 11:59) [4]

Четы по ADO в сервисе... Ты пробовал? Я да.
У меня веб сервер (на Indy) как сервис пишет логи в Access через ADO, динамические страницы берут данные из таблиц в разных ДБ тоже через ADO (добавление тоже имеется с транзакциями иногда), + небольшое клиент-сервер приложение обслуживает на ура


 
Slym ©   (2005-07-01 12:07) [5]

Нагрузка на сервер 1000-10000 постов в день
перфоманс каунтеры показывают 10-20 мс на запрос выборки
30-500 мс на запросы вставки
И не вылетает (тьфу, тьфу, тьфу)


 
NorthMan   (2005-07-01 12:13) [6]

2 Slym
Рад, что все так круто, но проблема есть и ее хотелось бы решить. Поясните, как лучше: динамически создавать экземпляр TAdoQuery или можно юзать компоненты, бросив их, например, на TDataModule? И как это все согласовать с потоками Indy


 
Digitman ©   (2005-07-01 12:54) [7]


> динамически создавать экземпляр TAdoQuery или можно юзать
> компоненты, бросив их, например, на TDataModule?


без разницы


> как это все согласовать с потоками Indy


Indy-потоки ничем не отличаются от любых иных наследников TThread


 
NorthMan   (2005-07-01 13:06) [8]

Спасибо, вроде начинаю разбираться. Вот только еще такая проблема возникает: когда пытаюсь делать AdoQuery.Open выдается ошибка OLE error 80030002. Инфы по этому поводу не много. Понял, что найти чего-то не может, но что конкретно? Путь к базе прописан, в DesignTime все открывается.


 
Digitman ©   (2005-07-01 13:09) [9]

CoInitialize/CoUninitialize выполняешь ?


 
Slym ©   (2005-07-01 13:29) [10]

TAdoQuery я бы создавал динамически в теле потока.
CoInitialize Нужно вызывать в главном потоке сервиса как минимум до подключения к ДБ  обычно на OnServiceStart и в перед созданием/подключением TAdoQuery в дочерних потоках, ну и соответственно CoUninitialize вконце


 
NorthMan   (2005-07-01 13:31) [11]

Выполняю, но при  CoInitialize(nil); получаю Access violation.... Что за фигня?


 
Digitman ©   (2005-07-01 13:39) [12]


> NorthMan   (01.07.05 13:31) [11]


приводи код


 
NorthMan   (2005-07-01 13:41) [13]

ага, понял, это не при CoInitialize(nil) происходит, а при AdoConnection.Open


 
NorthMan   (2005-07-01 13:49) [14]

Вот код:
procedure TDataModule1.RefreshTimerTimer(Sender: TObject);
var
 r_count: integer;
begin
   try
     r_count := 0;
     CoInitialize(nil);
     AdoConnection.Open;  //<-- тут вываливается
     GetInfoQuery.Open;
     r_count := GetInfoQuery.RecordCount;
     if r_count > 0 then
     begin
       GetInfoQuery.First;
       ...
  finally
    GetInfoQuery.Close;
    AdoConnection.Close;
    CoUninitialize;
  end;
end;


 
NorthMan   (2005-07-01 13:50) [15]

А SP2 XP-шный не может всю малину портить?


 
Digitman ©   (2005-07-01 13:52) [16]


> NorthMan   (01.07.05 13:49) [14]


в каком потоке создается DataModule1 ?

AdoConnection, GetInfoQuery - это компоненты, которые ты "бросил" на DataModule1 в дизайн-тайм ?


 
NorthMan   (2005-07-01 14:06) [17]

DataModule1 создается в основном потоке

AdoConnection, GetInfoQuery - это компоненты, которые ты "бросил" на DataModule1 в дизайн-тайм ?

Да


 
Digitman ©   (2005-07-01 14:20) [18]

т.е. и таймер лежит там же, на DataModule1 ?

а зачем он вообще нужен ?

и зачем в основном потоке нужны явные CoInitialize/CoUninitialize , если они и так уже неявно выполняются в ходе иниц-ции/деиниц-ции модуля ActiveX ?


> тут вываливается


с каким исключением ?


 
NorthMan   (2005-07-01 14:25) [19]

а зачем он вообще нужен ?

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

с каким исключением ?

Access violation at address 0048BD98 in module "Server.exe". Read of address 00000178


 
Digitman ©   (2005-07-01 14:31) [20]


> чтобы выборка производилась периодически, и заполнялись
> некоторые глобальные переменные


и что далее происходит с выборкой и этими глоб.переменными ?

ЧЕМ собственно поток сервиса (не путать с основным потоком сервис-процесса !) все это время (с момента старта до момента останова сервиса) у тебя занят ?


 
NorthMan   (2005-07-01 14:44) [21]

Погоди, что-то я запарился. Идея вот какая:
Создаем пустое приложение  типа Service Application. Добавляем в него DataModule. На DM помещаем таймер, Connection и Query. По таймеру выполняем приведенный выше код. Больше никаких действий не производится. Пусть в качестве глобальной переменной будет количество записей в Query. Беда в том, что Query не открывается, а вываливает исключение.


 
Digitman ©   (2005-07-01 15:09) [22]


> NorthMan   (01.07.05 14:44) [21]



> Создаем пустое приложение  типа Service Application


при описанной тобой логике я не вижу никакого резона реализации ее именно в сервис-приложении

объясни, зачем тебе понадобилось именно сервис-приложение ?
нем не устраивает обычное ?


 
NorthMan   (2005-07-01 15:30) [23]

Сервис будет обслуживать запросы клиентов (использую Indy TCPServer/TCPClient), но до этого еще надо разобраться, почему из службы не удается прочитать таблицы. По-прежнему вываливает исключение "OLE error 80030002".


 
Digitman ©   (2005-07-01 15:35) [24]


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


разве обычное приложение, использующее те же самые TCPServer/TCPClient, не в состоянии точно так же обслуживать те же самые запросы ?


 
NorthMan   (2005-07-01 15:45) [25]

все так, только эта служба должна работать на контроллере домена. Соответственно, интерфейс не нужен и должна работать под системной учетной записью.


 
Digitman ©   (2005-07-01 15:53) [26]

ты отладь взаимодействие IdTCPServer"а и ADO в обычном приложении !

а уж потом ты этот отлаженный алгоритм легко перенесешь в сервис и тогда уже будешь думать о проблемах доступа к АДО в сервисе под системной уч.записью ..

перенести ведь несложно - создаешь/активируешь IdTCPServer в OnServiceStart, деактивируешь/уничтожаешь в OnServiceStop ...


 
Digitman ©   (2005-07-01 15:57) [27]

но я так и не понял, зачем нужен таймер ...

выборку же можно (и нужно !) делать по запросу клиента, а если клиент "молчит" (подключился и ничего не "просит"), то зачем же вхолостую молотить ?


 
NorthMan   (2005-07-01 16:11) [28]

хорошо, учту совет, спасибо!


 
Slym ©   (2005-07-04 10:01) [29]

Ты AdoConnection.Free нигде не делаешЪ?
Зачем AdoConnection постоянно открывать/закрывать?
Тело потока:
begin
 CoInitialize(nil);
try
 GetInfoQuery:=TADOQuery.Create(nil);
 try
   GetInfoQuery.Connection:=AdoConnection;
   GetInfoQuery.LockType:=ltReadOnly;
   GetInfoQuery.Open;
   while not GetInfoQuery.EOF do
   begin
     ...
     GetInfoQuery.Next;
   end;
 finally
   GetInfoQuery.Free;
 end;
finally
 CoUninitialize;
end;
 {псевдокод}Socket.WriteResult(MyResult);
end;


 
Reindeer Moss Eater ©   (2005-07-04 14:28) [30]

Погоди, что-то я запарился. Идея вот какая:
Создаем пустое приложение  типа Service Application. Добавляем в него DataModule. На DM помещаем таймер, Connection и Query.


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


 
NorthMan   (2005-07-06 14:19) [31]

Все заработало, спасибо!



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

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

Наверх




Память: 0.55 MB
Время: 0.062 c
3-1126093049
Пантелеев Иван
2005-09-07 15:37
2005.10.23
Поиск + Подставление зап.


14-1128254007
Piter
2005-10-02 15:53
2005.10.23
Подскажите адреса серверов eMule


2-1128335255
Wolferio
2005-10-03 14:27
2005.10.23
Проверка папки по указаному пути.


14-1128424599
Андрей Жук
2005-10-04 15:16
2005.10.23
Покритикуйте


14-1127905420
MadAngel
2005-09-28 15:03
2005.10.23
Прикол?