我有一个动态库,在动态库中有一个全局的对象,这个对象需要在动态库被加载时初始化,动态库被全部释放时释放(没有其他人在调用它时)。
测试后发现在释放动态库时,总是出现死等。后来跟踪代码发现,出现在这个全局对象中的一个线程释放是,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;
测试后发现在释放动态库时,总是出现死等。后来跟踪代码发现,出现在这个全局对象中的一个线程释放是,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;
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.