Sky*_*Sky 6 delphi multithreading thread-safety delphi-2010
我必须修改和更改一个线程中的一些可视组件,因为你知道这样做是不安全的.
我的问题是如何编写完全线程安全的代码?有可能的?如果是的话那么请你举个简单的例子吗?
我的代码不是线程安全的:
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;
Run Code Online (Sandbox Code Playgroud)
谢谢.
在Delphi中编写线程安全代码涉及到任何其他语言的基本护理,这意味着要处理竞争条件.当不同的线程访问相同的数据时会发生竞争条件.处理这个问题的一个好方法是声明一个TCriticalSection实例并将危险代码包装在其中.
下面的代码显示了一个getter和一个属性的setter,通过hypotesis,有一个竞争条件.
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;
Run Code Online (Sandbox Code Playgroud)
请注意使用单个TCriticalSection(CriticalX)实例来序列化对数据成员FX的访问.
但是,对于Delphi,您有一个额外的考虑因素!VCL不是线程安全的,因此为了避免VCL竞争条件,任何导致屏幕更改的操作都必须在主线程中运行.你可以通过在Synchronize方法中调用这样的代码来实现.考虑到上面的类,你应该做这样的事情:
procedure TMyThread.ShowX;
begin
Synchronize(SyncShowX);
end;
procedure TMyThread.SyncShowX;
begin
ShowMessage(IntToStr(FX));
end;
Run Code Online (Sandbox Code Playgroud)
如果你有Delphi 2010或更高版本,有一种更简单的方法可以使用匿名方法:
procedure TMyThread.ShowX;
begin
Synchronize(procedure begin
ShowMessage(IntToStr(FX));
end);
end;
Run Code Online (Sandbox Code Playgroud)
我希望这有帮助!
您应该只从主VCL线程访问VCL对象.
一些读取方法(属性获取器)在实践中可以从其他线程开始工作 - 但是您必须事先为特定的Delphi构建读取VCL源代码.或者不使用它.
PS:Synchronize方法在主VCL线程中运行给定的程序,暂停调用程序线程,如果主线程也被阻塞,这可能导致死锁.
阅读更多:(实际上这个答案列出了一些链接)
Sky*_*Sky -2
我的问题解决了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;
Run Code Online (Sandbox Code Playgroud)
谢谢大家对我的帮助。