访问 FireMonkey 组件时自定义 class 中的线程安全
Thread-safety in custom class when accessing FireMonkey component
我正在编写自定义 class,它应该能够连接到表单上的 TMemo FireMonkey 组件,以便向其记录信息。 class 定义为:
TBlokData = class
private
[weak] FLogMemo: TMemo;
procedure Log(s : string);
public
constructor Create(ConnStr: string);
property LogMemo : TMemo read FLogMemo write FLogMemo;
destructor Destroy; override;
end;
Log
方法的实现是:
procedure TBlokData.Log(s : string);
begin
if Assigned(FLogMemo) then
FLogMemo.Lines.Add(TimeToStr(Now) + ': ' + s);
end;
如果我在线程中创建 class 对象并使用 FireMonkey 表单上的 Memo1
组件填充 LogMemo
属性,我会担心,我的 class 将不再是线程安全的,因为我将在调用 Log
方法时从线程操作表单上的组件。
这是一个有效的问题吗?如果是这样,如何在线程环境之外保持 class' 可用性的同时使其成为线程安全的?
你的担心是对的。您的代码不是线程安全的。使用 TThread.Synchronize
或 TThread.Queue
以确保对 UI 控件的任何操作都在主 UI 线程上执行。
一般而言,对 UI 组件的任何操作都必须在 UI 线程上执行。
创建方法LogThreadSafe
:
TThread.Synchronize(nil, procedure
begin
Log(s);
end);
我正在编写自定义 class,它应该能够连接到表单上的 TMemo FireMonkey 组件,以便向其记录信息。 class 定义为:
TBlokData = class
private
[weak] FLogMemo: TMemo;
procedure Log(s : string);
public
constructor Create(ConnStr: string);
property LogMemo : TMemo read FLogMemo write FLogMemo;
destructor Destroy; override;
end;
Log
方法的实现是:
procedure TBlokData.Log(s : string);
begin
if Assigned(FLogMemo) then
FLogMemo.Lines.Add(TimeToStr(Now) + ': ' + s);
end;
如果我在线程中创建 class 对象并使用 FireMonkey 表单上的 Memo1
组件填充 LogMemo
属性,我会担心,我的 class 将不再是线程安全的,因为我将在调用 Log
方法时从线程操作表单上的组件。
这是一个有效的问题吗?如果是这样,如何在线程环境之外保持 class' 可用性的同时使其成为线程安全的?
你的担心是对的。您的代码不是线程安全的。使用 TThread.Synchronize
或 TThread.Queue
以确保对 UI 控件的任何操作都在主 UI 线程上执行。
一般而言,对 UI 组件的任何操作都必须在 UI 线程上执行。
创建方法LogThreadSafe
:
TThread.Synchronize(nil, procedure
begin
Log(s);
end);