FireDac 冻结 GUI

FireDac freezes GUI

我在 Delphi 10.1 Berlin 下使用 FireDac。

为了向用户显示数据,我使用数据感知控件,如 TDBEdit。

我使用 TFDQuery 和 TDataSource link 它们与控件。

这可行,但需要一些时间才能执行的长 sql 查询会冻结 GUI。

我想知道如何在执行那些长 运行 查询时阻止 gui 冻结。

我在考虑后台线程。

在 wiki 上我读到 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 服务器检索记录的方法 在使用 FireDAC 的后台线程中。这省略了一些细节。例如,在实践中,而不是 TQueryThreads Execute 只打开一次查询然后终止,您可能希望线程的 Execute 包含一个 while 循环,它在其中等待调用 Synchronize 之后的信号量,然后 close/re-open 查询以根据需要更新主线程。

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,如您所料 "wire them together",然后设置 FDConnection 的 Params 和 FDQuery 的 Sql.