繁体   English   中英

Delphi中的线程安全

[英]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;

注意,使用TCriticalSectionCriticalX )的单个实例来序列化对数据成员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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM