delphi – FireDac冻结GUI

我正在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写道:

One thing I didn’t see asked or Dmitry mention is you can not have
TDataSource or LiveBindings against your background threaded queries.
If you are background threading a query that displays the results you
should disconnect the LB or DataSource,open and fetch all the data
then re establish the connection.

Those two will be trying to move the cursor on you or querying the
buffer for display while the buffer is very volatile being moved
around in a different thread.

我想知道是否有人也使用FireDac并在表单上显示值可以帮助我在这里.

解决方法

下面的代码示例显示了从MSsql Server中检索记录的一种方法
在使用FireDAC的后台线程中.这省略了一些细节.例如,在实践中,而不是TQueryThreads Execute只打开一次然后终止查询,你可能希望线程的Execute包含一个while循环,在调用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.在配置组件方面,我所做的只是将组件拖离Palette,按照您的预期将它们“连接在一起”,然后设置FDConnection的Params和FDQuery的sql.

相关文章

 从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都...
  从网上看到《Delphi API HOOK完全说明》这篇文章,基本上...
ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c+&#x...
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和ED...
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的...