哪个线程方法应该使用Synchronize?

Mar*_*unu 5 delphi multithreading

我知道Synchronize必须在Execute程序中使用,但它是否应该用于Create和Destroy方法,或者做任何我想要的安全吗?

Dav*_*nan 8

我知道Synchronize必须在Execute过程中使用.

这有点模糊.Synchronize当您拥有必须在主线程上执行的代码时,您需要使用.因此,您是否需要使用的答案在Synchronize很大程度上取决于所考虑的代码实际上做了什么.您必须问自己的问题,以及只有您可以回答的问题,您是否拥有必须在主线程上运行的代码?

作为一般规则,如果您不需要Synchronize在Execute方法之外打电话,那将被认为是谨慎的.如果你能找到避免这样做的方法那么那将是明智之举.请记住,线程的理想情况是,Synchronize如果可能的话,它们永远不需要阻塞.


您可能还希望考虑哪个线程执行构造函数和析构函数.

构造函数Create在调用它的线程中运行.它不会在新创建的线程中运行.因此,您不太可能需要在Synchronize那里使用.

析构函数Destroy在调用它的线程中运行.通常,这是调用Free线程对象的线程.通常,这将从最初创建线程的同一线程调用.常见的例外是从FreeOnTerminate线程调用Free的线程.


mgh*_*hie 5

Synchronize()当代码在应用程序的主 (GUI) 线程的上下文之外执行时,需要使用。因此,您的问题的答案取决于是否从该线程调用构造函数和析构函数。

如果您不确定,可以通过将 Windows API 函数的结果GetCurrentThreadId()与变量进行比较来检查MainThreadID——如果它们相等,则代码在主线程的上下文中执行。

已FreeOnTerminate设置的线程将从另一个线程上下文调用其析构函数,因此您需要使用Synchronize()或Queue()。或者你使用 VCL 已经提供的终止事件,我相信它是在主线程中执行的,但请查看文档以获取详细信息。


Dis*_*ned 5

首先,你不想Synchronize()不必要地打电话,因为这完全违背了使用线程的目的.因此,决定应基于:(a)是否可能遇到共享数据的竞争条件.(b)您将使用通常必须在主线程上运行的VCL代码.

您不太可能需要在构造函数中进行同步,因为TThread实例通常已经从主线程创建.(例外情况是,如果你是TThread从另一个子线程创建一些.)

注意:它不会造成任何伤害,因为Synchronize()已经检查你是否在主线程上并且如果你是的话会立即调用synchronized方法.

class procedure TThread.Synchronize(ASyncRec: PSynchronizeRecord; QueueEvent: Boolean = False);
var
  SyncProc: TSyncProc;
  SyncProcPtr: PSyncProc;
begin
  if GetCurrentThreadID = MainThreadID then
    ASyncRec.FMethod
Run Code Online (Sandbox Code Playgroud)

至于析构函数,有3种使用模式:

  • 的TThread情况下破坏自己.
  • 另一个线程(可能是主线程)可以WaitFor完成实例,然后销毁它.
  • 你可以拦截这个OnTerminate事件.实例完成后会触发此操作,然后您可以销毁它.

注:本OnTerminate次活动将已经被同步.

procedure TThread.DoTerminate;
begin
  if Assigned(FOnTerminate) then Synchronize(CallOnTerminate);
end;
Run Code Online (Sandbox Code Playgroud)

鉴于上述情况,您可能需要同步的唯一时间是线程是否自毁.

但是,我建议您避免将代码放入可能需要同步的析构函数中.如果您需要从线程实例OnTerminate获得一些计算结果,那么更合适的地方就是这样.