gpt4 book ai didi

multithreading - 在线程(Delphi)中打开查询时关闭表单时出错

转载 作者:行者123 更新时间:2023-12-03 19:41:08 38 4
gpt4 key购买 nike

我有一个Query,并在我的Thread中打开它。它可以正常工作,我不想使用Synchronize,因为Synchronize使得主FormQuery未完成提取时不响应。
当关闭显示的Form blow错误时:

系统错误。代码:1400。无效的窗口句柄

type
TMyThread = class(TThread)
public
procedure Execute; override;
procedure doProc;
end; { type }
.
.
.
procedure TMyThread.doProc;
begin
Form1.Query1.Open;
end;

procedure TMyThread.Execute;
begin
inherited;

doProc;
end;
.
.
.
procedure TForm1.Button1Click(Sender: TObject);
begin
thrd := TMyThread.Create(True);
thrd.FreeOnTerminate := True;
thrd.Resume;
end;

注意: Query有很多记录。

最佳答案

问题在于,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;

在Button1的 OnClick中,您将执行以下操作:
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;

最后,将清理代码分配给线程的终止处理程序。
如果销毁线程中的Query,则不能使用 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;

关于multithreading - 在线程(Delphi)中打开查询时关闭表单时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23196509/

38 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com