延迟DLL指令导致FireDAC查询上的应用程序死锁

Ale*_*lex 2 delphi dll deadlock firedac delphi-xe5

我在Delphi XE5中以下列方式设置了一个应用程序:

main.exe:使用export delayed指令调用sub.dll中的函数

function MyFunction: boolean; external 'sub.dll' delayed;
Run Code Online (Sandbox Code Playgroud)

sub.dll:包含运行简单SELECT查询的FireDAC查询对象.

在打开查询时,使用延迟指令,当主窗体关闭时,应用程序不会终止(进程main.exe保留在任务管理器中).进程资源管理器显示了sub.dll的剩余线程.当我没有指定延迟指令时,main.exe进程正确终止.我错过了什么?我觉得我没有释放一个物体,但我无法弄清楚它是什么.

简化代码:

MAIN.EXE:

program Main;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

  function MyFunction: boolean; external 'Sub.dll' delayed;

begin
  try
    MyFunction;
  except
    on E: Exception do begin
      Writeln(E.ClassName, ': ', E.Message);
      readln;
    end;
  end;
end.
Run Code Online (Sandbox Code Playgroud)

Sub.dll

library Sub;

uses
  System.SysUtils,
  System.Classes,
  DBConn in 'DBConn.pas';

{$R *.res}

function MyFunction: boolean; export;
var Conn: TConn;
begin
  Conn := TConn.Create;
  Conn.Destroy;
  Result := True;
end;

exports
  MyFunction;

begin
end.
Run Code Online (Sandbox Code Playgroud)

DBConn.pas

unit DBConn;

interface

uses
  FireDAC.Stan.Intf, FireDAC.Stan.Option,
  FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def,
  FireDAC.Phys, FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Stan.Param,
  FireDAC.DatS, FireDAC.DApt.Intf, FireDAC.DApt, FireDAC.VCLUI.Wait,
  FireDAC.Comp.UI, FireDAC.Phys.ODBCBase, FireDAC.Phys.ASA, Data.DB,
  FireDAC.Comp.DataSet, FireDAC.Comp.Client;

type
  TConn = class
    FDConnection: TFDConnection;
    FDQuery: TFDQuery;

    constructor Create;
    destructor Destroy; override;
  end;

var
  Conn: TConn;

{ TConn }

implementation

constructor TConn.Create;
begin
  FDConnection := TFDConnection.Create(nil);
  //Set database connection parameters
  with FDConnection do begin
    close; Params.Clear;
    Params.Add('DriverID=ASA');
    Params.Add('Database=');
    Params.Add('Server=');
    Params.Add('USER_NAME=');
    Params.Add('PASSWORD=');
    open;
  end;
  FDQuery := TFDQuery.Create(nil);
  with FDQuery do begin
    Connection := FDConnection;
    close; unprepare; SQL.Clear;
    SQL.Add('Select first LAST_NAME');
    SQL.Add('From USERS');
    SQL.Add('Order By LAST_NAME');
    prepare; open; //this causes the deadlock
    writeln(Output, FieldByName('LAST_NAME').AsString);
  end;
end;

destructor TConn.Destroy;
begin
  FDConnection.Close;
  FDConnection.Free;
  inherited;
end;

end.
Run Code Online (Sandbox Code Playgroud)