我正在Delphi 10.1 Berlin下使用FireDac。
为了向用户显示数据,我使用TDBEdit等数据感知控件。
我使用TFDQuery和TDataSource将它们与控件链接起来。
这可行,但需要一些时间才能执行的长SQL查询会冻结GUI。
我想知道如何在执行那些长时间运行的查询时阻止gui冻结。
我在考虑背景线程。
在维基上,我读到FireDac可以使用多线程: http://docwiki.embarcadero.com/RADStudio/XE6/en/Multithreading_(FireDAC)
然而在embarcadero社区论坛thread Jeff Overcash写道:
我没有看到的一件事或德米特里提到的是你不能拥有的 针对后台线程查询的TDataSource或LiveBindings。 如果您是背景线程,则会显示一个显示结果的查询 应断开LB或DataSource,打开并获取所有数据 然后重新建立连接。
这两个人会试图将光标移动到您身上或查询 缓冲区用于显示,而缓冲区非常易于移动 在另一个线程中。
我想知道是否有人也使用FireDac并在表单上显示值可以帮助我。
答案 0 :(得分:5)
下面的代码示例显示了从MSSql Server中检索记录的一种方法
在使用FireDAC的后台线程中。这省略了一些细节。例如,在实践中,您可能希望线程的TQueryThread
包含一个while循环,而不是Execute
s Execute
只打开一次查询然后终止。它在调用Synchronize
之后等待信号量,然后关闭/重新打开查询以根据需要更新主线程。
type
TForm1 = class;
TQueryThread = class(TThread)
private
FConnection: TFDConnection;
FQuery: TFDQuery;
FForm: TForm1;
published
constructor Create(AForm : TForm1);
destructor Destroy; override;
procedure Execute; override;
procedure TransferData;
property Query : TFDQuery read FQuery;
property Connection : TFDConnection read FConnection;
property Form : TForm1 read FForm;
end;
TForm1 = class(TForm)
FDConnection1: TFDConnection;
FDQuery1: TFDQuery;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
DBNavigator1: TDBNavigator;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
public
QueryThread : TQueryThread;
end;
[...]
constructor TQueryThread.Create(AForm : TForm1);
begin
inherited Create(True);
FreeOnTerminate := True;
FForm := AForm;
FConnection := TFDConnection.Create(Nil);
FConnection.Params.Assign(Form.FDConnection1.Params);
FConnection.LoginPrompt := False;
FQuery := TFDQuery.Create(Nil);
FQuery.Connection := Connection;
FQuery.SQL.Text := Form.FDQuery1.SQL.Text;
end;
destructor TQueryThread.Destroy;
begin
FQuery.Free;
FConnection.Free;
inherited;
end;
procedure TQueryThread.Execute;
begin
Query.Open;
Synchronize(TransferData);
end;
procedure TQueryThread.TransferData;
begin
Form.FDQuery1.DisableControls;
Form.FDQuery1.Data := Query.Data;
Form.FDQuery1.EnableControls;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
QueryThread.Resume;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
QueryThread := TQueryThread.Create(Self);
end;
MJN关于书签的评论告诉你如何保留gui中的当前数据行位置。
不过,虽然我经常使用TClientDataSets做到这一点,但是这个答案是我第一次尝试使用FireDAC。在配置组件方面,我所做的只是将组件拖离组件,"将它们连接在一起"正如您所期望的那样,然后设置FDConnection的Params和FDQuery的Sql。