Советы по Delphi. Версия 1.4.3 от 1.1.2001 - страница 29
Эти требования обязательны при разработке многопользовательских приложений Delphi с использованием файлов Dbase или Paradox.
– Ted Bulmanski
Выполнение запросов к базе данных в фоне
Delphi 2
Тема: Выполнение запросов к базе данных в фоновом потоке
Данный документ объясняет как выполнить запрос в фоновом режиме, используя класс TThread. Для получения общей информации о классе TThread, пожалуйста обратитесь к документации Borland и электронной справке. Для понимания данного документа вам необходимо иметь представление о том, как работать с компонентами для работы с базами данных, поставляемых в комплекте с Delphi 2.0.
Для осуществления потокового запроса необходимо выполнение двух требований. Во-первых, потоковый запрос должен находиться в своей собственной сессии с использованием отдельного компонента TSession. Следовательно, на вашей форме должен находиться компонент TSession, имя которого должно быть назначено свойству SessonName компонента TQuery, используемого для выполнения потокового запроса. Для каждого используемого в потоке компонента TQuery вы должны использовать отдельный компонент TSession. При использовании компонента TDataBase, для отдельного потокового запроса должен также использоваться отдельный TDataBase. Второе требование заключается в том, что компонент TQuery, используемый в потоке, не должен подключаться в контексте это потока к TDataSource. Это должно быть сделано в контексте первичного потока.
Приведенный ниже пример кода иллюстрирует описываемый процесс. Данный модуль демонстрирует форму, которая содержит по два экземпляра следующих компонентов: TSession, TDatabase, TQuery, TDataSource и TDBGrid. Данные компоненты имеют следующие значения свойств:
>Session1
> Active True;
> SessionName "Ses1"
>DataBase1
> AliasName "IBLOCAL"
> DatabaseName "DB1"
> SessionName "Ses1"
>Query1
> DataBaseName "DB1"
> SessionName "Ses1"
> SQL.Strings "Select * from employee"
>DataSource1
> DataSet ""
>DBGrid1
> DataSource DataSource1
>Session2
> Active True;
> SessionName "Ses2"
>DataBase2
> AliasName "IBLOCAL"
> DatabaseName "DB2"
> SessionName "Ses2"
>Query2
> DataBaseName "DB2"
> SessionName "Ses2"
> SQL.Strings "Select * from customer"
>DataSource2
> DataSet ""
>DBGrid1
> DataSource DataSource2
Обратите внимание на то, что свойство DataSet обоих компонентов TDataSource первоначально никуда не ссылается. Оно устанавливается во время выполнения приложения, и это проиллюстрировано в коде.
>unit Unit1;
>interface
>uses Windows, Messages, SysUtils, Classes, Graphics, Controls,Forms, Dialogs,StdCtrls, Grids, DBGrids, DB, DBTables;
>type
> TForm1 = class(TForm)
> Session1: TSession;
> Session2: TSession;
> Database1: TDatabase;
> Database2: TDatabase;
> Query1: TQuery;
> Query2: TQuery;
> DataSource1: TDataSource;
> DataSource2: TDataSource;
> DBGrid1: TDBGrid;
> DBGrid2: TDBGrid;
> GoBtn1: TButton;
> procedure GoBtn1Click(Sender: TObject);
> end;
> TQueryThread = class(TThread)
> private
>FSession: TSession;
> FDatabase: TDataBase;
> FQuery: TQuery;
> FDatasource: TDatasource;
> FQueryException: Exception;
> procedure ConnectDataSource;
> procedure ShowQryError;
> protected
> procedure Execute; override;
> public
> constructor Create(Session: TSession; DataBase: TDatabase; Query: TQuery; DataSource: TDataSource); virtual;
> end;
>var Form1: TForm1;
>implementation
>constructor TQueryThread.Create(Session: TSession; DataBase: TDatabase; Query: TQuery; Datasource: TDataSource);
>begin
> inherited Create(True); // Создаем поток c состоянием suspendend
> FSession := Session; // подключаем все privat-поля
> FDatabase := DataBase;
> FQuery := Query;
> FDataSource := Datasource;
> FreeOnTerminate := True; // Устанавливаем флаг освобождения потока после его завершения
> Resume; // Продолжение выполнения потока
>end;
>procedure TQueryThread.Execute;
>begin
> try
>{ Выполняем запрос и подключаем источник данных к компоненту TQuery, вызывая ConnectDataSource из основного потока(для этой цели используем Synchronize)}
> FQuery.Open;
> Synchronize(ConnectDataSource);
> except
>{ Ловим исключение (если оно происходит) и его дескриптор в контексте основного потока (для этой цели используемSynchronize). }