問題是,VCL是而不是線程安全。
爲了讓查詢與所有其他事情並行執行,您必須將其與表單分離。
這意味着你將不得不使用代碼在運行時創建查詢:
type
TMyThread = class(TThread)
private
FQuery: TQuery;
FOnTerminate: TNotifyEvent;
public
constructor Create(AQuery: TQuery);
destructor Destroy; override;
procedure Execute; override;
procedure doProc;
//Add an event handler to do cleanup on termination.
property OnTerminate: TNotifyEvent read FOnTerminate write FOnTerminate;
end; { type }
constructor TMyThread.Create(AQuery: TQuery);
begin
inherited Create(True);
FQuery:= AQuery;
end;
procedure TMyThread.doProc;
begin
FQuery1.Open;
Synchronize(
//anonymous method, use a separate procedure in older Delphi versions
procedure
begin
Form1.Button1.Enabled:= true; //reenable the button when we're done.
end
);
end;
procedure TMyThread.Execute;
begin
inherited;
doProc;
end;
destructor TMyThread.Destroy;
begin
if Assigned(FOnterminate) then FOnTerminate(Self);
inherited;
end;
在OnClick
爲Button1,你會做到以下幾點:
type
TForm1 = class(TForm)
private
AQuery: TQuery;
...
end; {type}
procedure TForm1.Button1Click(Sender: TObject);
begin
Button1.Enabled:= false; //disable the button so it cannot be started twice.
thrd.Free;
AQuery:= TQuery.Create;
AQuery.SQL.Text:= .....
thrd := TMyThread.Create(AQuery);
thrd.OnTerminate:= MyTerminationHandler;
thrd.FreeOnTerminate:= False;
thrd.Resume;
end;
最後清理代碼分配給線程的終止處理程序。 如果你在線程中銷燬查詢,那麼你不能使用FreeOnTerminate:= true
,但你必須自己釋放線程。
procedure TForm1.MyTerminationHandler(Sender: TObject);
begin
FreeAndNil(AQuery);
end;
警告
此代碼只會工作,如果你開始1個線程。
如果你想啓動這個線程多次(即運行在同一時間多個查詢),你必須創建線程的數組,例如:
TQueryThreads = record
MyThread: TMyThread;
MyQuery: TQuery;
constructor Create(SQL: string);
end; {record}
TForm1 = class(TForm)
private
Threads: array of TQueryThreads;
....
end; {TForm1}
注意,該代碼將不會在工作BDE,因爲該庫不支持同時運行多個查詢
如果你想這樣做,你將不得不使用ZEOS或類似的東西。
按TLama的建議:
我建議BDE TQuery組件切換到ADO或下載類似ZEOS components。 BDE是非常過時的,並且有很多怪癖永遠不會被修復,因爲它不再被維護。
如果Form1
已關閉,則剩下的唯一問題是清理連接。
如果這是您的主要形式,那真的沒有關係,因爲您的整個應用程序都會關閉。
如果它不是您的主要表單,則需要通過填寫OnCanClose
處理程序來禁用關閉表單。
TForm1.CanClose(Sender: TObject; var CanClose: boolean);
begin
CanClose:= thrd.Finished;
end;
不要把查詢放在窗體上。使其成爲本地執行。使其與分鐘線保持隔離。 –
你的線程是由於它的'FreeOnTerminate'概念像扔紙飛機。你應該控制它。此外,表單中Query1對象的訪問可能不安全,很可能是您的問題的原因。最後,如果它是一個'TQuery'對象,那麼你使用的是過時的BDE,你可以升級到更新的東西。 – TLama