mirror of
https://github.com/loginov-dmitry/multithread.git
synced 2025-02-20 07:58:22 +02:00
Мелкая корректировка
This commit is contained in:
parent
4bfa10e443
commit
33f535f266
@ -2527,37 +2527,37 @@ end;
|
||||
Ответ прост: функция `UniApplication` возвращает соответствующую переменную класса `TUniGUIApplication`, объявленную в секции `threadvar`. При обработке запроса от пользователя:
|
||||
1. UniGui создаёт (либо получает из пула) поток, который будет отвечать за обработку запроса, пришедшего от браузера;
|
||||
2. Поток анализирует запрос, извлекает из него идентификатор сессии и отыскивает объект `TUniGUIApplication`, который соответствует данному идентификатору сессии;
|
||||
3. Поток сохраняет найденный объект `TUniGUIApplication` в переменной, объявленной в секции `threadvar`.
|
||||
3. Поток сохраняет найденный объект `TUniGUIApplication` в переменной, объявленной в секции `threadvar`;
|
||||
4. Поток запускает необходимые обработчики событий (например, OnClick). Из этих обработчиков событий можно смело вызывать функции `UniApplication`, `UniMainModule`, `MainmForm` и т.д.
|
||||
|
||||
:warning: **Внимание!** Следует быть осторожным при объявлении в секции `threadvar` некоторых типов (строки, динамические массивы, варианты, интерфейсы). Причины этого хорошо описаны в [официальной документации](http://docwiki.embarcadero.com/RADStudio/Rio/en/Variables_(Delphi)#Thread-local_Variables).
|
||||
|
||||
# 12. Работа с базой данных из дополнительного потока <a name="work_with_db"></a>
|
||||
|
||||
Лично я не рекомендую работать с базой данных из десктопного приложения напрямую. Намного перспективнее разработать, как сейчас модно говорить, "микросервис", который:
|
||||
а) будет находиться на том же компьютере, что и база данных (либо на соседнем сервере);
|
||||
б) сможет работать с базой данных по наиболее быстрому протоколу с минимальными сетевыми задержками;
|
||||
Лично я не рекомендую работать с базой данных из десктопного приложения напрямую. Намного перспективнее разработать, как сейчас модно говорить, "микросервис", который:
|
||||
а) будет находиться на том же компьютере, что и база данных (либо на соседнем сервере);
|
||||
б) сможет работать с базой данных по наиболее быстрому протоколу с минимальными сетевыми задержками;
|
||||
в) сможет принимать от клиентов с помощью JSON-запросов команды на запрос данных и изменение данных. При этом клиентскому приложению вообще необязательно использовать сущность "таблица базы данных", оно может оперировать понятием "объект бизнес-логики". Какие именно таблицы в БД используются для хранения данных объекта бизнес-логики, решает исключительно микросервис. Благодаря такому подходу значительно увеличивается производительность системы по сравнению с работой с базой данных напрямую, особенно в тех случаях, когда клиентское приложение находится на значительном удалении от базы данных, т.е. имеются высокие сетевые задержки;
|
||||
|
||||
:information_source: **Информация!** Если Вы до сих пор не работали с JSON и не знаете, что это такое, советую обязательно этот пробел заполнить, т.к. на текущий момент JSON является общепринятым форматом организации, хранения и передачи информации (как когда-то XML, только проще и удобнее).
|
||||
|
||||
Использование вспомогательного микросервиса:
|
||||
а) позволит повысить безопасность базы данных (TCP-порт для подключения к базе данных выводить наружу не требуется);
|
||||
Использование вспомогательного микросервиса:
|
||||
а) позволит повысить безопасность базы данных (TCP-порт для подключения к базе данных выводить наружу не требуется);
|
||||
б) позволит использовать любую бесплатную базу данных (SQLite, Firebird, PostgreSQL и др., а также NoSql базы данных), при этом приложению-клиенту даже не нужно знать, какая база данных используется;
|
||||
в) позволит изменять правила обработки бизнес-логики без необходимости обновления приложений-клиентов;
|
||||
|
||||
В любом случае, каким бы образом Вы не работали с базой данных (напрямую из десктопного приложения или через вспомогательный микросервис), Вам никуда не деться от использования дополнительного потока для работы с базой данных. Конечно, в простейших случаях в десктопном приложении Вы можете всё общение с базой данных организовать из основного потока. Более того, некоторые компоненты умеют работать с базой данных в асинхронном режиме. Некоторые компоненты умеют показывать на экране вспомогательную модальную форму, которая появляется каждый раз, когда выполняется обращение к базе данных. Но давайте посмотрим недостатки этих подходов:
|
||||
|
||||
а) при работе с БД напрямую из основного подхода интерфейс пользователя будет тормозить в тех случаях, если выполняется "тяжелый" запрос, либо имеются очень длительные сетевые задержки;
|
||||
б) использование асинхронного режима может очень сильно запутать программу. В такой программе будет очень сложно (иногда даже невозможно) разбираться. Хорошо, если компонент доступа к БД позволяет навесить обработчик события получения данных (например, OnDataLoaded) в стиле анонимной процедуры, иначе, при использовании обычных методов, придётся как-то организовывать сохранение контекста обработки данных;
|
||||
а) при работе с БД напрямую из основного подхода интерфейс пользователя будет тормозить в тех случаях, если выполняется "тяжелый" запрос, либо имеются очень длительные сетевые задержки;
|
||||
б) использование асинхронного режима может очень сильно запутать программу. В такой программе будет очень сложно (иногда даже невозможно) разбираться. Хорошо, если компонент доступа к БД позволяет навесить обработчик события получения данных (например, OnDataLoaded) в стиле анонимной процедуры, иначе, при использовании обычных методов, придётся как-то организовывать сохранение контекста обработки данных;
|
||||
в) если при каждом запросе показывать на экране вспомогательную форму (или даже курсор с песочными часиками), то пользователям будет неприятно пользоваться такой программой.
|
||||
|
||||
Если программа достаточно навороченная, то у неё должны быть различные автоматические операции, выполняемые по расписанию, либо через заданный период времени, например:
|
||||
|
||||
а) автоматическая передача последних накопленных данных в центральную базу данных (например, из точек продаж, либо из филиалов большой организации);
|
||||
б) выгрузка данных для их дальнейшей обработки в 1С или иной внешней системе;
|
||||
в) обработка файла с данными, подготовленными во внешней системе;
|
||||
г) автоматическая передача данных в облачный сервис (например, передача последних пробитых чеков в ОФД);
|
||||
а) автоматическая передача последних накопленных данных в центральную базу данных (например, из точек продаж, либо из филиалов большой организации);
|
||||
б) выгрузка данных для их дальнейшей обработки в 1С или иной внешней системе;
|
||||
в) обработка файла с данными, подготовленными во внешней системе;
|
||||
г) автоматическая передача данных в облачный сервис (например, передача последних пробитых чеков в ОФД);
|
||||
д) и бесконечное множество других вариантов.
|
||||
|
||||
Надеюсь, читателю теперь стало очевидно, что очень важно уметь работать с базой данных из дополнительного потока.
|
||||
@ -2568,17 +2568,17 @@ end;
|
||||
|
||||
Причины этого следующие:
|
||||
|
||||
а) некоторые компоненты подключения к БД не рассчитаны на одновременную работу с ними из нескольких потоков (в том числе TIBDataBase). Внутри компонентов находятся различные списки, например список подключенных объектов TIBDataSet или список транзакций. Эти списки не всегда защищены от одновременного доступа;
|
||||
а) некоторые компоненты подключения к БД не рассчитаны на одновременную работу с ними из нескольких потоков (в том числе TIBDataBase). Внутри компонентов находятся различные списки, например список подключенных объектов TIBDataSet или список транзакций. Эти списки не всегда защищены от одновременного доступа;
|
||||
б) компонент подключения устанавливает соединение с сервером управления базы данных (СУБД) (например, по протоколу TCP/IP) и дальнейний обмен с СУБД осуществляется по принципу "запрос / ответ". Если один поток выполнил запрос к БД, то компонент подключения передаёт информацию в СУБД и ждёт ответа от СУБД. До тех пор, пока не будет ответа от СУБД, компонент подключения не будет передавать в СУБД новые запросы, даже если они поступают из других потоков. Таким образом, нет никакого смысла пытаться работать с базой данных из нескольких потоков с использованием одного компонента подключения.
|
||||
|
||||
:information_source: **Информация!** Очень важно при многопоточной работе с БД иметь пул подключений. Пул подключений - это по сути массив (список), в котором хранятся активные подключения к БД. Благодаря использованию пулов Вы экономите значительное время на процедуру установки соединения с БД, особенно если используется TLS-шифрование канала связи. Если Вы используете компоненты IBX для работы с Firebird, то можете использовать пул подключений из библиотеки [ibxFBUtils](https://github.com/loginov-dmitry/ibxfbutils). Данный пул я использую в различных коммерческих проектах более 10 лет, поэтому можно быть уверенным, что в нём всё вылизано досконально.
|
||||
|
||||
Итак, типовая работа с базой данных в дополнительном потоке выглядит следующим образом:
|
||||
|
||||
1. Создаём объект подключения либо берём готовое подключение из пула;
|
||||
2. Создаём объект-транзакцию (при необходимости);
|
||||
3. Выполняем необходимые запросы к базе данных;
|
||||
4. Коммитим транзакцию (если была произведена модификация данных в БД);
|
||||
1. Создаём объект подключения либо берём готовое подключение из пула;
|
||||
2. Создаём объект-транзакцию (при необходимости);
|
||||
3. Выполняем необходимые запросы к базе данных;
|
||||
4. Коммитим транзакцию (если была произведена модификация данных в БД);
|
||||
5. Уничтожаем объект подключения либо возвращаем его обратно в пул.
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user