【问题标题】:Delphi FireDAC TFDQuery event 'AfterOpen' never executesDelphi FireDAC TFDQuery 事件“AfterOpen”从不执行
【发布时间】:2016-02-22 16:14:47
【问题描述】:

我正在尝试异步执行 sql 查询。我检查了来自http://docwiki.embarcadero.com/RADStudio/XE5/en/Asynchronous_Execution_(FireDAC)的示例代码

还有目录中的示例项目

..Samples\Object Pascal\Database\FireDAC\Samples\Comp Layer\TFDQuery\ExecSQL\Async

我想我明白了里面的逻辑。但是有一个问题 - 事件QueryAfterOpen 永远不会执行,而我的TDataSource 始终保持Nil(因为它在QueryBeforeOpen 中得到Nil - 此事件始终执行)。这是我单位的所有代码:

unit Unit1;
interface
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, FireDAC.Stan.Intf,   
  FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf, 
  FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys,       
  FireDAC.VCLUI.Wait, FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf, FireDAC.DApt,
  Vcl.StdCtrls, Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client,    
  FireDAC.Phys.MySQLDef, FireDAC.Phys.MySQL;

type
  TForm1 = class(TForm)
  Button1: TButton;
  FDPhysMySQLDriverLink1: TFDPhysMySQLDriverLink;
  procedure FormCreate(Sender: TObject);
  procedure Button1Click(Sender: TObject);
  procedure Query1BeforeOpen(DataSet: TDataSet);
  procedure Query1AfterOpen(DataSet: TDataSet);
  procedure FormDestroy(Sender: TObject);

private
  { Private declarations }
  Connection1: TFDConnection;
  Query1: TFDQuery;
  DataSource1: TDataSource;
public
  { Public declarations }
end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
  var
    QueryFinished: Boolean;
begin
  with Query1 do begin
    SQL.Text := 'SELECT field1 FROM test_table WHERE idpk=1';
    AfterOpen := Query1AfterOpen;
    BeforeOpen := Query1BeforeOpen;
    ResourceOptions.CmdExecMode := amAsync;
    QueryFinished := False;
    Open;
    repeat
      Sleep(100);
      if Command.State = csPrepared then begin
          // A command is prepared. A result set is not accessible.
        // TmpInteger := Query1.FieldByName('field1').AsInteger;
      end
      else if Command.State = csOpen then begin // A command execution
         // is finished. A result set is accessible and not yet fully fetched.
        if DataSource1.DataSet <> Nil then begin 
          // this code never executes because Query1AfterOpen never executes and 
          // DataSource1.DataSet remains always Nil !!!
          QueryFinished := True;
        end;
      end;
    until ((QueryFinished) OR (DataSource1.DataSet <> Nil));
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
  var
    SQLConnParams: string;
  begin
    SQLConnParams := ''; // sql connection parameters removed from here from security 
    // issues, assume they are correct
    Connection1 := TFDConnection.Create(Nil);
    Connection1.Params.Text := SQLConnParams;
    Query1 := TFDQuery.Create(Nil);
    Query1.Connection := Connection1;
    DataSource1 := TDataSource.Create(Nil);
    DataSource1.DataSet := Query1;
  end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  DataSource1.Free;
  Query1.Free;
  Connection1.Free;
end;

procedure TForm1.Query1AfterOpen(DataSet: TDataSet);
begin
  DataSource1.DataSet := Query1;
  Query1.AfterOpen := Nil;
  //Query1.ResourceOptions.CmdExecMode := amBlocking;
end;

procedure TForm1.Query1BeforeOpen(DataSet: TDataSet);
begin
  DataSource1.DataSet := Nil;
end;
end.

显然repeat .. until .. 循环内的代码是无限的,除非有人终止程序。为了在Query1AfterOpen 中执行代码(或改用另一个事件),我缺少什么以便在TFDQuery 完成工作后访问结果集?

【问题讨论】:

    标签: delphi firedac


    【解决方案1】:

    那些异步事件通过消息循环与主线程同步。只要您留在Button1Click 事件中,就无法处理任何新消息。因此,AfterOpen 事件被卡在消息循环中。

    我不知道您要达到什么目的,但您应该考虑将相关代码放在 AfterOpen 事件中。 repeat-until 子句以某种方式伪造了异步执行的目的。

    【讨论】:

    • 我正在等待查询完成它的工作并返回一个结果集或在发生某些事情时取消它的工作(例如有人引发异常标志) - 这就是我想使用异步的原因TFDQuery。我只是从一个更大的项目中获取代码并将其放在 Button1Click 中 - 但我们假设 Button1Click 是在 TThread.Execute 事件中执行的过程。
    • 如果您正在等待查询完成,您最好坚持使用amBlocking,因为这正是您需要的。 amAsync 仅在调用 open 后不需要直接结果集时才有意义。有趣的是,当您确实将代码放在“TThread.Execute”方法中时,您的代码可能会按预期工作,因为在这种情况下,您不会阻塞消息队列。但是,您在同步变量访问时还会遇到其他问题。
    • 但它仍然无法正常工作 - Query1AfterOpen 事件仍未到达。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    • 2018-05-08
    • 1970-01-01
    • 2019-06-27
    • 1970-01-01
    相关资源
    最近更新 更多