我可以将 Delphi TThread.Synchronize() 本地移动到 VCL 表单以从主线程或工作线程调用吗?
Can I move Delphi TThread.Synchronize() locally to a VCL form to be called from both a main or worker thread?
我正在将 CreateAnonymousThread 用于工作任务,当我开始使用它时,我根据记录的示例在整个声明中使用了 Synchronize,例如:
procedure Txxx.RunWorker;
begin
FExecutionThread := TThread.CreateAnonymousThread(procedure ()
begin
TThread.Synchronize (TThread.CurrentThread,
procedure ()
begin
// Here before worker stuff
NotifyBeforeWorkerStuff;
end);
// Do worker stuff
TThread.Synchronize (TThread.CurrentThread,
procedure ()
begin
// Here after worker stuff
NotifyAfterWorkerStuff;
end);
end);
FExecutionThread.Start;
end;
end;
如您所见,在此线程中,我向我的应用程序的各个部分启动事件通知,包括 VCL 表单(NotifyBeforeWorkerStuff 等)。
后来,我看到我可以将 Synchronize() 更本地地移动到每个 VCL 表单,接近实际需要它来更新(非安全)VCL 控件的点:
procedure TSomeVCLForm.ReceiveNotification;
begin
TThread.Synchronize (TThread.CurrentThread,
procedure ()
begin
Label1.Caption := GetSomeStringFunction;
end);
end;
只要我接受来自主线程或工作线程的通知,工作线程就会变得更简单:
procedure Txxx.RunWorker;
begin
FExecutionThread := TThread.CreateAnonymousThread(procedure ()
begin
NotifyBeforeWorkerStuff;
// Do worker stuff
NotifyAfterWorkerStuff;
end);
FExecutionThread.Start;
end;
关于这是否正确,我有几个问题:
- 我的通知可能来自工作线程,也可能来自主线程(例如来自按钮按下)。那么,当从主线程调用 VCL 窗体上的 'ReceiveNotification' 时,是否允许像上面那样调用 TThread.Synchronize? the XE8 docs 暗示不是,但检查 System.Classes 这看起来没问题,而且工作正常。
- 在 'ReceiveNotification' 中,当 Label1.Caption 从 GetSomeStringFunction 获取字符串时,即使调用来自工作线程,也绝对不需要在该函数内锁定是否正确?
感谢任何建议。
文档说:
Warning: Do not call Synchronize from within the main thread. This can cause an infinite loop.
我认为文档是完全错误的。 XE8 中的实现检查当前线程是否为主线程。如果是,则直接执行该方法。
ReceiveNotification
中不需要锁定,因为对 GetSomeStringFunction
的调用始终在主线程上执行。
我正在将 CreateAnonymousThread 用于工作任务,当我开始使用它时,我根据记录的示例在整个声明中使用了 Synchronize,例如:
procedure Txxx.RunWorker;
begin
FExecutionThread := TThread.CreateAnonymousThread(procedure ()
begin
TThread.Synchronize (TThread.CurrentThread,
procedure ()
begin
// Here before worker stuff
NotifyBeforeWorkerStuff;
end);
// Do worker stuff
TThread.Synchronize (TThread.CurrentThread,
procedure ()
begin
// Here after worker stuff
NotifyAfterWorkerStuff;
end);
end);
FExecutionThread.Start;
end;
end;
如您所见,在此线程中,我向我的应用程序的各个部分启动事件通知,包括 VCL 表单(NotifyBeforeWorkerStuff 等)。 后来,我看到我可以将 Synchronize() 更本地地移动到每个 VCL 表单,接近实际需要它来更新(非安全)VCL 控件的点:
procedure TSomeVCLForm.ReceiveNotification;
begin
TThread.Synchronize (TThread.CurrentThread,
procedure ()
begin
Label1.Caption := GetSomeStringFunction;
end);
end;
只要我接受来自主线程或工作线程的通知,工作线程就会变得更简单:
procedure Txxx.RunWorker;
begin
FExecutionThread := TThread.CreateAnonymousThread(procedure ()
begin
NotifyBeforeWorkerStuff;
// Do worker stuff
NotifyAfterWorkerStuff;
end);
FExecutionThread.Start;
end;
关于这是否正确,我有几个问题:
- 我的通知可能来自工作线程,也可能来自主线程(例如来自按钮按下)。那么,当从主线程调用 VCL 窗体上的 'ReceiveNotification' 时,是否允许像上面那样调用 TThread.Synchronize? the XE8 docs 暗示不是,但检查 System.Classes 这看起来没问题,而且工作正常。
- 在 'ReceiveNotification' 中,当 Label1.Caption 从 GetSomeStringFunction 获取字符串时,即使调用来自工作线程,也绝对不需要在该函数内锁定是否正确?
感谢任何建议。
文档说:
Warning: Do not call Synchronize from within the main thread. This can cause an infinite loop.
我认为文档是完全错误的。 XE8 中的实现检查当前线程是否为主线程。如果是,则直接执行该方法。
ReceiveNotification
中不需要锁定,因为对 GetSomeStringFunction
的调用始终在主线程上执行。