繁体   English   中英

Delphi FireDAC TFDQuery事件'AfterOpen'永远不会执行

[英]Delphi FireDAC TFDQuery event 'AfterOpen' never executes

我正在尝试异步执行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完成工作后访问结果集?

这些异步事件通过消息循环与主线程同步。 只要您留在Button1Click事件内,就不能处理新消息。 因此,AfterOpen事件被卡在消息循环中。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM