[英]Thread-safe in delphi
我必须修改和更改线程中的某些可视组件,并且您知道这样做不安全。
我的问题是如何编写完全线程安全的代码? 有可能的? 如果可以,请给我一个简单的例子吗?
我的代码不是线程安全的:
type
tMyWorkerThread = class(TThread)
public
procedure Execute; override;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure tMyWorkerThread.Execute;
begin
//codes
//working with visual components
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
TMyWorkerThread.Create(false);
end;
谢谢。
用Delphi编写线程安全代码涉及您使用任何其他语言所需要的基本护理,即处理竞争条件 。 当不同的线程访问相同的数据时,就会发生竞争状态。 处理该问题的一种好方法是声明TCriticalSection的实例,然后将危险代码包装在其中。
下面的代码显示了一个属性的获取器和设置器,通过假设,该属性具有竞争条件。
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;
我希望这有帮助!
您只能从主VCL线程访问VCL对象。
实际上,某些读取方法(属性获取器)可以在其他线程上工作-但是您必须事先为特定的Delphi构建读取VCL源代码进行证明。 还是不使用它。
PS:同步方法在主VCL线程中运行给定过程,暂停调用者线程,如果主线程也被阻塞,则可能导致死锁。
阅读更多:(实际上是回答这个问题以列出一些链接)
我的问题通过Synchronize!
解决了Synchronize!
type
tMyWorkerThread = class(TThread)
public
procedure Execute; override;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure tMyWorkerThread.Execute;
begin
//codes that takes long time
Synchronize(procedure begin
//working with visual components
end
);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
TMyWorkerThread.Create(false);
end;
谢谢大家的帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.