使用dbExpress时,FreeLibrary会冻结(TSQLConnection)

时间:2015-11-12 16:54:47

标签: delphi dll dbexpress

我目前正在开发一些简单的自动更新程序应用程序。最重要的特征是自我更新的可能性。这就是我计划将大多数逻辑放在外部DLL中的原因。在我的DLL增长了一点后,我开始在主应用程序中遇到FreeLibrary调用问题。在dll调试期间,我发现函数负责该bug:

function TpmDSServerUpdateDownloader.DownloadUpdates: Boolean;
var
  LSQLConnection: TSQLConnection;
  LSQLServerMethod: TSqlServerMethod;
  LUpdatePackageLink: string;
begin
  try
    {$IFDEF DEBUG}
    Sleep(10000);
    {$ENDIF}
    // Getting update package link
    FUpdateServerIP := '127.0.0.1';
    FUpdateServerPort := 8080;
    LSQLConnection := TSQLConnection.Create(nil);
    LSQLServerMethod:= TSQLServerMethod.Create(nil);
    LSQLConnection.DriverName :='DataSnap';
    LSQLConnection.LoginPrompt := False;
    LSQLConnection.Params.Add('CommunicationProtocol=HTTP');
    LSQLConnection.Params.Add('Hostname=' + FUpdateServerIP);
    LSQLConnection.Params.Add('Port=' + IntToStr(FUpdateServerPort));
    LSQLConnection.Params.Add('ConnectTimeout=' + IntToStr(10000));
    LSQLConnection.Connected := True;
    LSQLServerMethod.SQLConnection:= LSQLConnection;
    LSQLServerMethod.ServerMethodName:= 'TServerMethods1.GetUpdatePackageLink';
    LSQLServerMethod.Params[0].AsInteger := 1;
    LSQLServerMethod.ExecuteMethod;
    LUpdatePackageLink := LSQLServerMethod.Params[1].AsString;
    // Downloading update package with LUpdatePackage link
  finally
    LSQLConnection.Connected := False;
    LSQLServerMethod.Free;
    FreeAndNil(LSQLConnection);
  end;
end;

当我使用该函数的dbExpress组件时,会出现问题。我想知道释放TSQLConnection / TSQLServerMethod是否会留下一些有效的dbExpress线程/对象,就像在IBObjects中使用SQLMonitor一样。也许你有一些想法如何解决?我非常感谢你的帮助。

问候 米甲

1 个答案:

答案 0 :(得分:0)

这是一个Delphi错误。

但是有解决方案:

以下Microsoft关闭线程无法从DLL卸载中调用,因此FreeLibrary将在Data.DBXCommon的初始化部分中创建的TDBXScheduler的TThread.WaitFor proc中的WaitForMultipleObject inifinite循环上进行冻结,并在其中自动关闭该单元的最终化部分。这会导致错误。因此,我们必须更早关闭该线程。

解决方案是您需要导出新过程并在FreeLibrary之前调用它:

   uses 
       Data.DBXCommon
    .....
    procedure FinishDLLWork; stdcall; export;
    begin
      TDBXScheduler.Instance.Free;
    end;

并在FreeLibrary之前调用它; 释放TDBXSchedulerTDBXScheduler.Instance会自动将其设置为Nil,因此此调用正常(请检查TDBXScheduler.Destroy;

很遗憾,它无法在DLL_THREAD_DETACHDLL_PROCESS_DETACH中调用-为时已晚。