Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2005.10.23;
Скачать: [xml.tar.bz2];

Вниз

Про 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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.039 c
14-1128068917
Igorek
2005-09-30 12:28
2005.10.23
А что Вы знаете о Гондурасе?


3-1126287172
Кабан
2005-09-09 21:32
2005.10.23
DBLocupLookupComboBox


4-1124694289
Fanny
2005-08-22 11:04
2005.10.23
Как обойтись без StrLCat ?


1-1128077265
Vladimir88
2005-09-30 14:47
2005.10.23
try ... finally except


2-1127909372
Grief
2005-09-28 16:09
2005.10.23
Изображения с палитрой





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский