【问题标题】:Is TThread.Synchronize evil / stillborn?TThread.Synchronize 是邪恶的/死产的吗?
【发布时间】:2017-04-28 12:59:12
【问题描述】:

我的印象是,应该至少可以从主线程控制的线程根本不能使用Synchronize():任何尝试这样做几乎都会立即导致死锁。

因此,onTerminate 事件也应该避免,因为它是使用 Synchronize 调用的。

例如,我有一个线程可以做一些艰苦的后台工作。如果用户按下关闭按钮,我想在状态栏中查看它的进度并能够“优雅地”停止它。

我不能使用FreeOnTerminate := true,因为当线程启动时,我根本不能调用它的任何方法:在任何时候它都可能被破坏并且我会遇到访问冲突(或完全破坏某些东西)。

所以,线程销毁是主线程的责任。在某种 DoTerminate 过程中完成所有“完成”工作并将 onTerminate 事件指向它是合乎逻辑的。但这是死锁:我们无法从 DoTerminate 中释放线程,因为在 TThread.Free 中有 WaitFor 在同步的 onTerminate 事件完成之前无法完成。

不仅仅是 OnTerminate:如果工作线程中有任何 Synchronize 调用(例如,它想通知我们已经完成了某些百分比的工作等),如果此时主线程正在运行,则可能出现死锁用工作线程做某事:他们互相阻塞!

所以,据我了解,使用 Synchronize 的唯一方法是将所有调用委托给工作线程端!例如,我们使用FreeOnTerminate := true 创建它,它有时使用 Synchronize() 来告诉我们它的进度,或者它已经完成并且将被销毁。只有在这些过程中我们才能控制它,但它使“随意”优雅关闭几乎不可能或过于复杂。

我是否遗漏了什么(一些有助于以某种方式克服这些僵局的内部工作)?因为我有点惊讶: Synchronize() 是 Delphi 多线程手册中描述的第一种方法。真的这么没用吗?

【问题讨论】:

  • 你能发布你的代码吗?我在这里试过,效果很好。
  • 为什么这个问题被否决了?没有示例代码,我完全理解这一点。
  • Synchronize 本身不是问题。程序架构是。例如,在持有临界区气味的同时调用 Synchronize(这 可以 没问题......但更可能是灾难的根源)。 Synchronize 的问题在于如何让线程相互通信。

标签: multithreading delphi synchronization


【解决方案1】:

Synchronize 有完全有效的用例,但您必须小心识别这些用例是什么,并确保您正在编写代码,以便明确避免出现死锁情况的可能性。这是完全可能的,但需要仔细设计。

您通常只应在需要工作线程等待主线程完成工作后再继续工作时使用Synchronize。在大多数情况下,这不是必需的,通常应该首选使用TThread.Queue。使用Queue 将工作发布到主线程,然后立即返回,而无需等待主线程处理工作。这避免了大多数与使用 Synchronize 相关的死锁陷阱。

Queue 的唯一危险是主线程超载。如果您的工作人员将工作发布到主线程的速度超过了主线程可以跟上的速度,那么您最终可能会遇到主线程锁定处理排队工作的情况。

【讨论】:

    猜你喜欢
    • 2011-01-02
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    • 1970-01-01
    • 2016-11-18
    • 2010-11-26
    • 2020-08-10
    • 2010-12-23
    相关资源
    最近更新 更多