在 Delphi 中编写线程安全代码涉及到您在任何其他语言中都会有的基本注意事项,这意味着处理竞争条件。当不同的线程访问相同的数据时,就会出现竞争条件。处理这个问题的一个好方法是声明一个TCriticalSection的实例并将危险代码包装在其中。
下面的代码显示了一个属性的 getter 和 setter,根据假设,该属性具有竞争条件。
constructor TMyThread.Create;
begin
CriticalX := TCriticalSection.Create;
end;
destructor TMyThread.Destroy; override;
begin
FreeAndNil(CriticalX);
end;
function TMyThread.GetX: string;
begin
CriticalX.Enter;
try
Result := FX;
finally
CriticalX.Leave;
end;
end;
procedure TMyThread.SetX(const value: string);
begin
CriticalX.Enter;
try
FX := Value;
finally
CriticalX.Leave;
end;
end;
注意使用TCriticalSection ( CriticalX )的单个实例来序列化对数据成员FX的访问。
但是,使用 Delphi,您还有一个额外的考虑!VCL 不是线程安全的,因此为了避免 VCL 竞争条件,任何导致屏幕更改的操作都必须在主线程中运行。您可以通过在Synchronize方法中调用这样的代码来获得它。考虑到上面的类,你应该这样做:
procedure TMyThread.ShowX;
begin
Synchronize(SyncShowX);
end;
procedure TMyThread.SyncShowX;
begin
ShowMessage(IntToStr(FX));
end;
如果您有Delphi 2010或更高版本,则有一种更简单的方法可以使用匿名方法:
procedure TMyThread.ShowX;
begin
Synchronize(procedure begin
ShowMessage(IntToStr(FX));
end);
end;
我希望这有帮助!