我有一个动态库,在动态库中有一个全局的对象,这个对象需要在动态库被加载时初始化,动态库被全部释放时释放(没有其他人在调用它时)。
测试后发现在释放动态库时,总是出现死等。后来跟踪代码发现,出现在这个全局对象中的一个线程释放是,waitfor处死等。再后来写了段测试代码,发现在动态库中建一条全局的线程,动态库释放时都会出现死等。
unit TradeDataInterface;interfaceuses
  ThreadTest,
  Windows, Classes, SysUtils, Forms, ActiveX;var
  AThread: TThreadTest; // 测试的全局线程implementation
initialization
  CoInitialize(nil);
  AThread:= TThreadTest.Create(False);finalization
  AThread.Terminate;
  AThread.WaitFor; // 出现死等
  AThread.Free;
  AThread:= nil;
  CoUninitialize;end.
线程部分代码unit ThreadTest;interfaceuses
  Classes, SysUtils;type
  TThreadTest = class(TThread)
  protected
    procedure Execute; override;
  end;implementation{ TThreadTest }procedure TThreadTest.Execute;
begin
  inherited;
  while not Terminated do
    Sleep(100);
end;end.
看线程的 waitfor 函数,发现线程的 线程句柄等于主线程的句柄了,GetCurrentThreadID = MainThreadID ,又改为不用waitfor,自己去WaitForSingleObject(AThread.Handle),但仍旧出现死等。
很迷惑,线程明明释放了,为什么死等呢。function TThread.WaitFor: LongWord;
var
  H: array[0..1] of THandle;
  WaitResult: Cardinal;
  Msg: TMsg;
begin
  H[0] := FHandle;
  if GetCurrentThreadID = MainThreadID then 
  begin
    WaitResult := 0;       // 执行到这里面了,即 GetCurrentThreadID = MainThreadID
    H[1] := SyncEvent;
    repeat
      { This prevents a potential deadlock if the background thread
        does a SendMessage to the foreground thread }
      if WaitResult = WAIT_OBJECT_0 + 2 then
        PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE);
      WaitResult := MsgWaitForMultipleObjects(2, H, False, 1000, QS_SENDMESSAGE);
      CheckThreadError(WaitResult <> WAIT_FAILED);
      if WaitResult = WAIT_OBJECT_0 + 1 then
        CheckSynchronize;
    until WaitResult = WAIT_OBJECT_0;
  end else WaitForSingleObject(H[0], INFINITE);
  CheckThreadError(GetExitCodeThread(H[0], Result));
end;

解决方案 »

  1.   

    呵呵,问题解决了,你可以把解决的思路或者过程贴上来,然后让版主帮你结贴,把分给你.DLL当中通过DLL_PROCESS_ATTACH时创建,然后在DLL_PROCESS_DETACH销毁即可
    Library xxxx;
    uses
      windows;
    var
      ...;//这里声明全局变量procedure DllMain(Reason: Integer);
    var
      local_ARTransmit_gbl: ARTransmit_Caller;
      local_ARTransmit_rmt: ARTransmit_Caller;
    begin
      case Reason of
        DLL_PROCESS_ATTACH:begin
            //这里创建
          end;
        DLL_PROCESS_DETACH: begin
            //这里销毁
          end;    end;
      end;
    end;
    begin
      DLLProc := @DllMain;
    end.