2016-01-27 53 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 –