何时需要在TThread中同步?

4
我知道您需要使用 synchronize (yourprocedure) 来设置标签的文本。但是,那么读取标签的文本,切换/设置标签的启用属性以及调用其他标签的过程/函数(例如 onclick 事件)呢?
是否有一个简单的规则可以知道 / 记住何时需要使用 synchronize
另外:synchronize 是否类似于 PostMessage/SendMessage?
2个回答

10

简单的经验法则是:需要同步任何访问VCL UI组件,包括读写UI控件属性。 Win32界面,尤其是像MessageBox()TaskDialog()这样的对话框,可以在工作线程中直接使用而无需同步。

TThread.Synchronize()类似于SendMessage()(实际上,在Delphi 5及更早版本中,它内部使用了SendMessage())。 TThread.Queue()类似于PostMessage()


非常感谢。那么我确实需要执行很多程序/函数来进行同步。 - Ben

4
无论何时访问VCL UI组件,您都需要实现某种类型的线程安全措施。这也通常是在访问存在于其他线程中或将由另一个线程访问的变量或过程时的情况。然而,并不是所有这些情况都需要使用Synchronize方法。有其他可用工具,而Synchronize并不总是您最好的解决方案。
在执行您传递给它的过程时,Synchronize会阻止主线程和调用线程,因此过度使用它可能会削弱多线程的好处。Synchronize可能最常用于更新UI,但如果发现您必须经常使用它,则检查并查看是否可以重构代码可能不是坏主意。例如,在您的线程内部确实需要从标签中读取吗?您是否可以在启动线程之前读取标签并将其传递到线程的构造函数中?您是否可以在线程的OnTerminate事件处理程序中处理这些任务中的任何任务?

很遗憾,我需要在运行线程时进行偶尔的检查。我认为只要没有其他线程尝试设置/写入地址空间,读取值/属性不应该是问题。但是必须小心处理。 - Ben
1
您的措辞不太恰当。调用线程肯定被阻塞了,但主线程肯定没有被阻塞 - 如果是这样的话,它怎么能执行传递的过程呢? - mghie
1
主线程在执行传递的过程时被阻塞,也就是说,它不响应事件或执行任何其他任务。我相信我的陈述意思对于任何不是为了讨论语义而阅读它的人来说都是相当清楚的。 - Aaron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接