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

时间:2014-05-11 15:16:00

标签: multithreading delphi

我知道必须在Synchronize程序中使用Execute,但是它也应该在CreateDestroy方法中使用,或者我可以安全地执行任何操作要什么?

4 个答案:

答案 0 :(得分:8)

  

我知道必须在执行程序中使用Synchronize

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

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


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

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

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

答案 1 :(得分: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

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

  • TThread实例会摧毁自己。
  • 另一个线程(可能是主线程)可以WaitFor实例完成,然后将其销毁。
  • 您可以截取OnTerminate事件。当实例完成时会触发它,然后你就可以销毁它。

注意: OnTerminate事件已经同步

procedure TThread.DoTerminate;
begin
  if Assigned(FOnTerminate) then Synchronize(CallOnTerminate);
end;

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

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

答案 2 :(得分:4)

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

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

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

答案 3 :(得分:4)

添加其他答案中所说的内容......

您永远不会 需要 才能使用Synchronize。但是,Synchronize在以下情况下可能有用:

  1. 在线程的上下文中,您需要执行触及与主线程具有亲缘关系的对象的代码。
  2. 您需要阻止线程,直到代码执行完毕。
  3. 即使在这种情况下,还有其他方法可以实现相同的目标,但Synchronize提供了满足这两个需求的便捷方式。如果您只需要这两个项目中的一个,那么可以采用更好的策略。

    在主题#1上,明显的对象是用户界面对象。这些是与主线程具有线程亲和性的对象,仅仅是因为主线程不断地读取和写入这些对象的属性(至少因为它需要将它们绘制到屏幕上等),它确实所以方便。这意味着您的线程无法安全地访问这些组件,并保证主线程不会同时访问或修改它们。为了防止损坏,线程必须将工作传递给主线程(因为主线程一次只能做一件事,显然不能干扰自己)。 Synchronize只是将工作放在主线程的队列中,并等待主线程在返回之前完成它。

    这点到了第2点。您是否需要(或者,同样地,你能负担得起)等待主线程完成工作吗?有三种情况和两种选择。

    1. 是的,你可以或必须等待。 (Synchronize非常适合)
    2. 不,你等不及了。 (Synchronize不合适)
    3. 不在乎。 (Synchronize很简单,所以这是一个明智的选择)
    4. 如果您只是更新一个很快就会被覆盖的状态显示,并且您的线程有更紧迫的问题,那么将消息发布到主线程并继续执行操作可能是明智的。如果你的线程只是在等待什么都不做,主要是,并且不值得花时间编写任何更复杂的代码,那么Synchronize就好了,如果需要在将来如此需要,可以用更好的东西替换它。

      正如其他人所说,这实际上取决于你在做什么。我认为,至少从概念上讲,更重要的问题是要在需要担心并发性时以及何时不需要时进行整理。每当您有多个需要访问单个资源的线程时,您需要使用某种机制来协调该访问,以避免线程相互冲突。 Synchronize是其中一种方法,但它不是最不重要的,也不是最后一种方法。