2016-01-27 22 views
2

我在Delphi XE5设立在下列方式提出的申请:延迟DLL指令导致应用程序死锁

MAIN.EXE:要求使用出口延迟指令

function MyFunction: boolean; external 'sub.dll' delayed; 
在sub.dll功能

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. 

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. 

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. 
+0

您是否得到与空的TMyForm.ButtonClick处理程序相同的结果?如果没有,确切地说现有处理程序的哪些步骤是保留线程所必需的? – MartynA

+0

@MartynA你的意思是说,如果我移动查询成说,表单?是的,会发生相同的结果。 – Alex

+0

不,我的意思是,如果你根本没有打开FDConnection和FDQuery。 – MartynA

回答

-3

VCL将可靠在Dll中工作只有如果您的主Exe和Dll在相同版本的Delphi中编译并且启用了运行时软件包。

+2

这是过分简单化,事实上并非如此。经典计数器示例用于证明您的错误陈述是Office COM加载项。 –

+0

看到了。不能可靠地工作。我的意思是你应该仔细选择那些在这样的加载项中工作正常的组件。而这些组件的清单并不大。 – Torbins

+0

根本不是。用VCL编写的Office COM加载项运行良好。正如这一成功的证明:https://www.add-in-express.com/add-in-delphi/index.php –