Как реализовать соединение ADO в потоке HTTP TIdServerContext?

Я работал над HTTP-сервером (TIdHTTPServer), обрабатывающим событие OnCommandGet. Я только что создал унаследованный объект TIdServerContext и переопределил его конструктор и деструктор. Теперь я хотел бы переместить свое соединение с базой данных из предыдущего пользовательского объекта сеанса в этот поток контекста. Свойство KeepAlive сервера включено.

Цель состоит в том, чтобы повторно использовать подключения к базе данных, реализованные в каждом сеансе. В настоящее время каждый запрос порождает новое соединение ADO, и я бы хотел этого избежать. Я понимаю, что KeepAlive не обязательно означает весь сеанс входа/выхода из системы, а просто поддерживает постоянное соединение для экономии ресурсов.

Мой вопрос в том, как мне использовать мой унаследованный объект TIdServerContext для поддержания его собственного согласованного соединения с базой данных (TADOConnection), которое может использоваться (в правилах COM (CoInitialize)) для каждого запроса?

Я предполагаю, что любой код, который я добавляю в обработчик событий OnCommandGet, выполняется в том же контексте потока, что и унаследованный TIdServerContext - это правильно? По сути, это означает... Безопасно ли использование TIdServerContext.OnRun и TIdHTTPServer.OnCommandGet в одном потоке и COM?


person Jerry Dodge    schedule 07.08.2014    source источник


Ответы (1)


OnCommandGet действительно работает в том же потоке, что и TIdServerContext.

Вы не можете назначить свой собственный обработчик OnRun, потому что TIdCustomTCPServer уже использует это событие для запуска своего метода DoExecute(), который TIdHTTPServer переопределяет для запуска своих OnCommamd... событий.

Если вы хотите повторно использовать объект(ы) БД в нескольких запросах от одного и того же клиента, вы можете инициализировать COM и создать объект(ы) БД в событии OnConnect, а также освободить объект(ы) БД и освободить COM в событии OnDisconnect . Однако использование этих событий помогает только в том случае, если клиент запрашивает подтверждение активности при каждом запросе, что не является гарантией. Свойство TIdHTTPServer.KeepAlive позволяет серверу учитывать сообщения поддержки активности только по запросу, оно не заставляет клиентов запрашивать их. Если не запрошено, каждый запрос вызовет собственную пару событий OnConnect/OnDisconnect.

ADO основан на COM, поэтому он имеет сходство с потоками. Кроме того, COM следует инициализировать только один раз для каждого потока. Таким образом, вам лучше инициализировать COM и создать объект (ы) БД при запуске потока, а также освободить объект (ы) БД и освободить COM, когда поток завершится. По умолчанию серверы Indy используют новый поток для каждого клиентского соединения, поэтому, переключаясь на эту модель, вы по-прежнему получаете выгоду от аналогичного поведения, как если бы вы использовали события OnConnect/OnDisconnect. Независимо от того, использует ли клиент поддержку активности или нет, эффект одинаков.

Однако эта модель дает вам больше гибкости, потому что теперь вы можете включить объединение потоков на сервере (назначив TIdSchedulerOfThreadPool свойству TIdHTTPServer.Scheduler), а затем можете повторно использовать объект(ы) БД в нескольких клиентских подключениях, использующих один и тот же поток с течением времени. .

Получите новый класс от TIdThreadWithTask, переопределите его метод BeforeExecute(), чтобы инициализировать COM и создать объект(ы) БД, и переопределите его метод AfterExecute(), чтобы освободить объект(ы) БД и освободить COM. Назначьте этот класс свойству планировщика ThreadClass.

Чтобы получить доступ к объекту(ам) БД в событии OnCommand..., приведите свойство AContext.Yarn к типу TIdYarnOfThread, затем приведите его свойство Thread к производному классу, после чего вы сможете обращаться к его членам по мере необходимости.

Вы по-прежнему можете получить пользовательский класс TIdServerContext для обработки данных для каждого клиента (Indy не реализует объединение контекстов) и использовать объекты БД для каждого запроса по мере необходимости. Просто отделите создание/уничтожение объекта БД от класса контекста.

person Remy Lebeau    schedule 07.08.2014
comment
+ еще один виртуальный 1 для многочисленных правок :-) Это мне очень помогает. - person Jerry Dodge; 07.08.2014