您正在调用 ExitThread() 立即杀死线程这意味着 CoUninitialize() 调用不再执行。您不需要自己调用 ExitThread。正常退出线程功能就足够了。
try
// ...
finally
CoUnintialize;
Result := 1; // the value that you specified in the ExitThread() call
end;
调用 SuspendThread() 可能会暂停线程,但不会执行“finally”块,也不会离开 Calc() 函数,也不会终止线程。您需要在 Calc() 函数中添加“已终止”检查,以便线程可以正常终止。
编辑:
这是一个伪代码,它允许您的线程通过更改 Calc() 方法来优雅地终止以了解潜在的超时。
type
ECalcTimedOut = class(Exception);
TSpAu = class(...)
protected
FCalcTimedOut: Boolean;
procedure CheckCalcTimedOut;
end;
PTeste = ^TTeste;
TTeste = record
ptrClass: TSpAu;
ptrTEMPO: ^integer;
end;
function THREAD_CALCULO(PTR: pointer): longint; stdcall;
begin
CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
try
try
PTeste(PTR).ptrClass.Calc;
PTeste(PTR).ptrTEMPO^ := 1;
Result := 1;
except
on ECalcTimedOut do
Result := 0;
end;
finally
CoUninitialize;
end;
end;
procedure Calc_Prin;
var
TEMPO: integer;
RESULTADO: THandle;
thrID: DWord;
teste: TTeste;
begin
// ...
teste.ptrClass.FCalcTimedOut := False;
RESULTADO := CreateThread(nil, 0, @THREAD_CALCULO, @teste, 0, thrID);
if WaitForSingleObject(RESULTADO, TEMPO_PERMITIDO) = WAIT_TIMEOUT then
begin
// Signal the Calc() method that it timed out
teste.ptrClass.FCalcTimedOut := True;
// Wait for the thread to terminate gracefully
WaitForSingleObject(RESULTADO, INFINITE);
end;
CloseHandle(RESULTADO);
end;
procedure TSpAu.CheckCalcTimedOut;
begin
if FCalcTimedOut then
raise ECalcTimedOut.Create('Calc Timed out');
end;
procedure TSpAu.Calc;
begin
CheckCalcTimeout;
// do something
while condition do
begin
CheckCalcTimeout;
DoSomethingElse;
CheckCalcTimeout;
// do something
end;
end;
procedure TSpAu.DoSomethingElse;
begin
for I := 0 to 1000000 do
begin
CheckCalcTimeout;
// do something
end;
end;