constructor TQueryThread.Create(Session: TSession; DataBase:
TDatabase; Query: TQuery; Datasource: TDataSource);
begin
inherited Create(True); // Create thread in a suspendend state
FSession := Session; // connect all private fields
FDatabase := DataBase;
FQuery := Query;
FDataSource := Datasource;
FreeOnTerminate := True; // Have thread object free itself when terminated
Resume; // Resume thread execution
end;
procedure TQueryThread.Execute;
begin
try
{ Run the query and connect the datasource to the TQuery
component by calling ConnectDataSource from main
thread (Synchronize used for this purpose)}
FQuery.Open;
Synchronize(ConnectDataSource);
except
{ Capture exception, if one occurs, and handle it in the
context of the main thread (Synchonize used for this
purpose. }
FQueryException := ExceptObject as Exception;
Synchronize(ShowQryError);
end;
end;
procedure TQueryThread.ConnectDataSource;
begin
FDataSource.DataSet := FQuery; // Connect the DataSource to the TQuery
end;
procedure TQueryThread.ShowQryError;
begin
Application.ShowException(FQueryException); // Handle the exception
end;
procedure RunBackgroundQuery(Session: TSession; DataBase:
TDataBase; Query: TQuery; DataSource: TDataSource);
begin
{ Create a TThread instance with the various parameters. }
TQueryThread.Create(Session, Database, Query, DataSource);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
DataSource1.DataSet := nil; //데이타소스는 나중에 쓰레드의 synchronize 부분에서 연결함
Query1.Close;
Query1.SQL.Text := 'select count(*) from tb_refnd ';
RunBackgroundQuery(Session1, Database1, Query1, DataSource1);
Timer1.Enabled := true;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled := false;
ShowMessage('쿼리 시간 경과');
DBGrid1.Visible := false; //쿼리결과를 보여주지 않음
end;
다시 원점으로 돌아온 느낌이네요.
쿼리가 실행중일 때는
쓰레드를 강제종료해도 에러가 나네요.
쓰레드의 쿼리가 결국은 메인폼에 있는 쿼리고요.
쓰레드에서 따로 쿼리를 create 해서 한다고 해도(?) 같은 결과를
볼 거 같네요.
연 쿼리를 강제로 닫는 문제로 다시 돌아왔네요.
클라이언트단에서는 어려운 모양입니다.
서버단에서 가능한 방법이 있을런지요.
아시는 것처럼 쓰레드로 쿼리하는 방법이 대안이 될 거 같습니다.
그러면 쿼리하는 중에도 다른 작업(타이머로 시간을 체크함)이 가능하더라고요.
아래 사이트를 참조해서 코딩해봤습니다.
쓰레드에서 쿼리는 자신만의 세션을 요함.
http://bdn.borland.com/article/0,1410,16231,00.html
----------------------------------------------------------------------
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Grids, DBGrids, DBTables, Db, ExtCtrls;
type
TForm1 = class(TForm)
DataSource1: TDataSource;
Query1: TQuery;
Database1: TDatabase;
Session1: TSession;
DBGrid1: TDBGrid;
Button1: TButton;
Button2: TButton;
Timer1: TTimer;
procedure Button1Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
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
{$R *.DFM}
constructor TQueryThread.Create(Session: TSession; DataBase:
TDatabase; Query: TQuery; Datasource: TDataSource);
begin
inherited Create(True); // Create thread in a suspendend state
FSession := Session; // connect all private fields
FDatabase := DataBase;
FQuery := Query;
FDataSource := Datasource;
FreeOnTerminate := True; // Have thread object free itself when terminated
Resume; // Resume thread execution
end;
procedure TQueryThread.Execute;
begin
try
{ Run the query and connect the datasource to the TQuery
component by calling ConnectDataSource from main
thread (Synchronize used for this purpose)}
FQuery.Open;
Synchronize(ConnectDataSource);
except
{ Capture exception, if one occurs, and handle it in the
context of the main thread (Synchonize used for this
purpose. }
FQueryException := ExceptObject as Exception;
Synchronize(ShowQryError);
end;
end;
procedure TQueryThread.ConnectDataSource;
begin
FDataSource.DataSet := FQuery; // Connect the DataSource to the TQuery
end;
procedure TQueryThread.ShowQryError;
begin
Application.ShowException(FQueryException); // Handle the exception
end;
procedure RunBackgroundQuery(Session: TSession; DataBase:
TDataBase; Query: TQuery; DataSource: TDataSource);
begin
{ Create a TThread instance with the various parameters. }
TQueryThread.Create(Session, Database, Query, DataSource);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
DataSource1.DataSet := nil; //데이타소스는 나중에 쓰레드의 synchronize 부분에서 연결함
Query1.Close;
Query1.SQL.Text := 'select count(*) from tb_refnd ';
RunBackgroundQuery(Session1, Database1, Query1, DataSource1);
Timer1.Enabled := true;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled := false;
ShowMessage('쿼리 시간 경과');
DBGrid1.Visible := false; //쿼리결과를 보여주지 않음
end;
end.