![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Про Indy и синхронизацию потоков [D6, WinXP]
NorthMan © (2005-07-01 08:07:00)Народ, подскажите, как лучше сделать.
Проблема такая:
Есть idTCPServer. В OnExecute принимается запрос от клиента, затем нужно выполнить внешнюю процедуру типа TForm1.GetData, в которой выполняется запрос в базу через ADO (выполняется AThread.Synchronize(TForm1.GetData)), а результат запроса необходимо вернуть в OnExecute. Подскажите, как с т.з. потока правильнее передать результат запроса. Через глобальную переменную, как мне кажется, нельзя, т.к. клиентов в каждый момент времени может быть много.
NorthMan (2005-07-06 14:19:00) [1]Все заработало, спасибо!
Reindeer Moss Eater (2005-07-04 14:28:00) [2]Погоди, что-то я запарился. Идея вот какая:
Создаем пустое приложение типа Service Application. Добавляем в него DataModule. На DM помещаем таймер, Connection и Query.
В момент коннекта очередного клиента создать новый экземпляр этого модуля данных. Ссылку на него сохранить в присоединившемся клиенте.
При обработке запросов клиента работать с экземпляром модуля данных этого клиента.
Когда клиент сделал дисконнект, убивать его модуль данных.
Slym (2005-07-04 10:01:00) [3]Ты 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;
NorthMan (2005-07-01 16:11:00) [4]хорошо, учту совет, спасибо!
Digitman (2005-07-01 15:57:00) [5]но я так и не понял, зачем нужен таймер ...
выборку же можно (и нужно !) делать по запросу клиента, а если клиент "молчит" (подключился и ничего не "просит"), то зачем же вхолостую молотить ?
Digitman (2005-07-01 15:53:00) [6]ты отладь взаимодействие IdTCPServer'а и ADO в обычном приложении !
а уж потом ты этот отлаженный алгоритм легко перенесешь в сервис и тогда уже будешь думать о проблемах доступа к АДО в сервисе под системной уч.записью ..
перенести ведь несложно - создаешь/активируешь IdTCPServer в OnServiceStart, деактивируешь/уничтожаешь в OnServiceStop ...
NorthMan (2005-07-01 15:45:00) [7]все так, только эта служба должна работать на контроллере домена. Соответственно, интерфейс не нужен и должна работать под системной учетной записью.
Digitman (2005-07-01 15:35:00) [8]
> Сервис будет обслуживать запросы клиентов
разве обычное приложение, использующее те же самые TCPServer/TCPClient, не в состоянии точно так же обслуживать те же самые запросы ?
NorthMan (2005-07-01 15:30:00) [9]Сервис будет обслуживать запросы клиентов (использую Indy TCPServer/TCPClient), но до этого еще надо разобраться, почему из службы не удается прочитать таблицы. По-прежнему вываливает исключение "OLE error 80030002".
Digitman (2005-07-01 15:09:00) [10]
> NorthMan (01.07.05 14:44) [21]
> Создаем пустое приложение типа Service Application
при описанной тобой логике я не вижу никакого резона реализации ее именно в сервис-приложении
объясни, зачем тебе понадобилось именно сервис-приложение ?
нем не устраивает обычное ?
NorthMan (2005-07-01 14:44:00) [11]Погоди, что-то я запарился. Идея вот какая:
Создаем пустое приложение типа Service Application. Добавляем в него DataModule. На DM помещаем таймер, Connection и Query. По таймеру выполняем приведенный выше код. Больше никаких действий не производится. Пусть в качестве глобальной переменной будет количество записей в Query. Беда в том, что Query не открывается, а вываливает исключение.
Digitman (2005-07-01 14:31:00) [12]
> чтобы выборка производилась периодически, и заполнялись
> некоторые глобальные переменные
и что далее происходит с выборкой и этими глоб.переменными ?
ЧЕМ собственно поток сервиса (не путать с основным потоком сервис-процесса !) все это время (с момента старта до момента останова сервиса) у тебя занят ?
NorthMan (2005-07-01 14:25:00) [13]а зачем он вообще нужен ?
Таймер лежит на DataModule1 и нужен для того, чтобы выборка производилась периодически, и заполнялись некоторые глобальные переменные.
с каким исключением ?
Access violation at address 0048BD98 in module 'Server.exe'. Read of address 00000178
Digitman (2005-07-01 14:20:00) [14]т.е. и таймер лежит там же, на DataModule1 ?
а зачем он вообще нужен ?
и зачем в основном потоке нужны явные CoInitialize/CoUninitialize , если они и так уже неявно выполняются в ходе иниц-ции/деиниц-ции модуля ActiveX ?
> тут вываливается
с каким исключением ?
NorthMan (2005-07-01 14:06:00) [15]DataModule1 создается в основном потоке
AdoConnection, GetInfoQuery - это компоненты, которые ты "бросил" на DataModule1 в дизайн-тайм ?
Да
Digitman (2005-07-01 13:52:00) [16]
> NorthMan (01.07.05 13:49) [14]
в каком потоке создается DataModule1 ?
AdoConnection, GetInfoQuery - это компоненты, которые ты "бросил" на DataModule1 в дизайн-тайм ?
NorthMan (2005-07-01 13:50:00) [17]А SP2 XP-шный не может всю малину портить?
NorthMan (2005-07-01 13:49:00) [18]Вот код:
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:41:00) [19]ага, понял, это не при CoInitialize(nil) происходит, а при AdoConnection.Open
Digitman (2005-07-01 13:39:00) [20]
> NorthMan (01.07.05 13:31) [11]
приводи код