我知道必须在Synchronize
程序中使用Execute
,但是它也应该在Create
和Destroy
方法中使用,或者我可以安全地执行任何操作要什么?
答案 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
在以下情况下可能有用:
即使在这种情况下,还有其他方法可以实现相同的目标,但Synchronize
提供了满足这两个需求的便捷方式。如果您只需要这两个项目中的一个,那么可以采用更好的策略。
在主题#1上,明显的对象是用户界面对象。这些是与主线程具有线程亲和性的对象,仅仅是因为主线程不断地读取和写入这些对象的属性(至少因为它需要将它们绘制到屏幕上等),它确实所以方便。这意味着您的线程无法安全地访问这些组件,并保证主线程不会同时访问或修改它们。为了防止损坏,线程必须将工作传递给主线程(因为主线程一次只能做一件事,显然不能干扰自己)。 Synchronize
只是将工作放在主线程的队列中,并等待主线程在返回之前完成它。
这点到了第2点。您是否需要(或者,同样地,你能负担得起)等待主线程完成工作吗?有三种情况和两种选择。
Synchronize
非常适合)Synchronize
不合适)Synchronize
很简单,所以这是一个明智的选择)如果您只是更新一个很快就会被覆盖的状态显示,并且您的线程有更紧迫的问题,那么将消息发布到主线程并继续执行操作可能是明智的。如果你的线程只是在等待什么都不做,主要是,并且不值得花时间编写任何更复杂的代码,那么Synchronize
就好了,如果需要在将来如此需要,可以用更好的东西替换它。
正如其他人所说,这实际上取决于你在做什么。我认为,至少从概念上讲,更重要的问题是要在需要担心并发性时以及何时不需要时进行整理。每当您有多个需要访问单个资源的线程时,您需要使用某种机制来协调该访问,以避免线程相互冲突。 Synchronize
是其中一种方法,但它不是最不重要的,也不是最后一种方法。