我有这个帖子:
TWorkerThread = class(TThread)
private
FSignal: TEvent;
public
constructor Create;
destructor Destroy; override;
procedure Execute; override;
end;
constructor TWorkerThread.Create;
begin
FSignal := TEvent.Create(nil, false{ManualReset}, false, '');
inherited Create(false{CreateSuspended});
end;
destructor TWorkerThread.Destroy;
begin
Terminate;
FSignal.SetEvent;
WaitFor;
AlFreeAndNil(FSignal);
inherited;
end;
procedure TWorkerThread.Execute;
begin
while not Terminated do begin
....
fSignal.WaitFor(INFINITE);
end;
end;
好的,所以现在"有时"在我的主线程中我想释放这个帖子,但我不想等待它完成(不想阻止主线程),所以我现在不能打电话{ {1}}将执行MyThread.free
我想像这样做一些想法
waitFor
但是这可能会出错,想象一下当我打电话给 fMyWorkerThreads[i].FreeOnTerminate := True;
fMyWorkerThreads[i].Terminate;
fMyWorkerThreads[i].Signal.SetEvent;
fMyWorkerThreads[i] := nil;
时,如果我非常不走运,fMyWorkerThreads[i].Terminate;
之前被释放到了fMyWorkerThreads[i]
我将会有访问违规?
所以我该怎么办?如果我在fMyWorkerThreads[i].Signal.SetEvent;
之前拨打fMyWorkerThreads[i].Signal.SetEvent;
,我也可能不幸运行,fMyWorkerThreads[i].Terminate;
往返前往fMyWorkerThreads[i].execute
再次到达fSignal.WaitFor(INFINITE);
< / p>
答案 0 :(得分:-2)
简单的解决方案是不使用标准Terminate
。 警告:以下代码适用于您的抽象问题。这不是所有案例的模板。
interface
uses
System.Classes, System.SyncObjs;
type
TTestThread = class(TThread)
private
FSignal: TEvent;
protected
procedure Execute; override;
public
constructor Create;
destructor Destroy; override;
procedure CustomTerminate;
end;
procedure Test1();
procedure Test2();
implementation
uses
Winapi.Windows;
{ TTestThread }
constructor TTestThread.Create;
begin
FSignal := TEvent.Create(nil, True{must be true}, False, '');
inherited Create(False);
end;
procedure TTestThread.CustomTerminate;
begin
FSignal.SetEvent();
end;
destructor TTestThread.Destroy;
begin
CustomTerminate();
// this is standart way, but it will be much better to use one more own event
if not FreeOnTerminate then // without this check, will be deadlock
WaitFor;
FSignal.Free;
inherited;
end;
procedure TTestThread.Execute;
begin
// TEvent.WaitFor can end with an error. Read docs before use
while FSignal.WaitFor(0) = TWaitResult.wrTimeout do begin
FSignal.WaitFor(INFINITE);
end;
end;
procedure Test1();
var
T: TTestThread;
begin
T := TTestThread.Create();
try
Sleep(2000);
finally
T.Free;
end;
end;
procedure Test2();
var
T: TTestThread;
begin
T := TTestThread.Create();
Sleep(2000);
T.FreeOnTerminate := True;
T.CustomTerminate;
end;
<强>可是... 强>
你想在线程类之外使用FreeOnTerminate
,它可以很方便,但它引入了危险的混淆。在构造函数中使用此标志要好得多,或者根本不使用它。以下是您不应该使用它的更多原因:
FreeOnTerminate
,则线程对象不会被销毁。恕我直言:我不建议使用FreeOnTerminate
。
<强> UPD:强>
使用标准Terminate
的解决方案。
interface
uses
System.Classes, System.SyncObjs;
type
TTestThread = class(TThread)
private
FSignal: TEvent;
protected
procedure Execute; override;
procedure TerminatedSet; override;
public
constructor Create;
destructor Destroy; override;
end;
implementation
uses
Winapi.Windows;
{ TTestThread }
constructor TTestThread.Create;
begin
FSignal := TEvent.Create(nil, True, False, '');
inherited Create(False);
end;
destructor TTestThread.Destroy;
begin
Terminate;
// this is standart way, but it will be much better to use one more own event
if not FreeOnTerminate then // without this check, will be deadlock
WaitFor;
FSignal.Free;
inherited;
end;
procedure TTestThread.Execute;
begin
// TEvent.WaitFor can end with an error. Read docs before use
while FSignal.WaitFor(0) = TWaitResult.wrTimeout do begin
FSignal.WaitFor(INFINITE);
end;
end;
procedure TTestThread.TerminatedSet;
begin
FSignal.SetEvent();
end;
end;