Q&A

  • Thread를 사용한 Query 동시에 날리기
김영대님의 자료실에서 'Thread를 사용한 Query 동시에 날리기'를 찾아서 test를 하는중
'Name not unique in this context'라는 에러가 자꾸만 납니다.
Query안에 사용안 SQL문장도 에러가 없는것이고 DB연결도 잘했습니다.
어떻게 된건지 모르겠습니다. 꼭 좀 알려주세요!!!

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  DBTables, Db, StdCtrls, Grids, DBGrids, ComCtrls, ADODB;

type
  TForm1 = class(TForm)
    Database1: TDatabase;
    Query2: TQuery;
    Query3: TQuery;
    DataSource1: TDataSource;
    DataSource2: TDataSource;
    DataSource3: TDataSource;
    DBGrid1: TDBGrid;
    DBGrid2: TDBGrid;
    DBGrid3: TDBGrid;
    Button1: TButton;
    ProgressBar1: TProgressBar;
    Session1: TSession;
    Query1: TQuery;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TQueryThread = class(TThread)
  private
    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
  // thread object의 instance를 생성한다
  // Create의 파라미터가 False이면 thread를 생성한후 즉시 Execute를 호출하여 실행한다
  //            "        True이면 Resume을 호출하기 전까지 실행하지 않는다
  inherited Create(True);

  FDatabase := DataBase;
  FQuery := Query;
  FDataSource := Datasource;

  // thread의 실행이 종료하면 자동으로 free되게 설정
  FreeOnTerminate := True;

  // 실행이 일시 중지된(suspended) thread를 실행한다
  Resume;
end;

procedure TQueryThread.Execute;
begin
  try
    // Query를 open하고 DataSource를 연결한다  
    FQuery.Open;

    // thread간의 충돌을 피하여 ConnectDataSource 를 호촐한다
    Synchronize(ConnectDataSource);
  except
    // Handle the exception
    FQueryException := ExceptObject as Exception;
    // thread간의 충돌을 피하여 ShowQryError 를 호촐한다
    Synchronize(ShowQryError);
    // Do not use the properties and methods of other objects directly in the Execute method of a thread.
    // Instead, separate the use of other objects into a separate procedure call, and call that procedure
    // by passing it as a parameter to the Synchronize method.
  end;
end;

// TQuery object를 접근하므로 Synchronize 로 호출해야함
procedure TQueryThread.ConnectDataSource;
begin
  // DataSource를 연결한다
  // TQuery를 접근하므로 Synchronize 로 호출했음
  FDataSource.DataSet := FQuery;
end;

// Application object를 접근하므로 Synchronize 로 호출해야함
procedure TQueryThread.ShowQryError;
begin
  // Handle the exception
  Application.ShowException(FQueryException);
end;

procedure RunBackgroundQuery(Session: TSession; DataBase: TDataBase;
            Query: TQuery; DataSource: TDataSource);
begin
  {thread instance 생성}
  TQueryThread.Create(Session, Database, Query, DataSource);
end;

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  {병렬처리: 3개의 Query를 thread를 사용하여 open한다}
  RunBackgroundQuery(Session1, DataBase1, Query1, Datasource1);
  RunBackgroundQuery(Session1, DataBase1, Query2, Datasource2);
  RunBackgroundQuery(Session1, DataBase1, Query3, Datasource3);

(* 순차처리: 일반적인 Query Open
  Query1.Open;
  Query2.Open;
  Query3.Open;

  *)
  for i := 1 to 100 do
    ProgressBar1.Position := i;
end;

end.
0  COMMENTS