【问题标题】:while not terminated do block still can not exit a thread?虽然没有终止do块仍然不能退出线程?
【发布时间】:2015-10-25 08:14:06
【问题描述】:

昨天专家建议在线程执行函数中使用“while not terminate do begin...”来检查线程终止属性并从内部优雅地退出线程。我们刚刚测试了代码,但它仍然无法终止线程。但是这个线程可以通过在外部调用 TerminateThread 函数来立即终止。执行函数或执行函数中的那个大while循环有缺陷吗?或者在使用while未终止循环时有什么特殊要求?

顺便问一下,endthread、exitthread 和 terminatethread 有什么区别?如何使用它们?哪个比较好?

再次感谢您的帮助。

【问题讨论】:

  • 永远不要从外部杀死线程。它使应用程序处于未定义状态。
  • 您的线程很可能正在等待事件或类似事件。使用调试器来确定它在做什么。还值得一提的是 TThread.Waitfor,它允许您确保线程在释放之前停止。
  • TerminateThread 应重命名为 RandomlyDeadlockMyProcessAndOccasionallyCorruptMyMemory。
  • 期待下一版Delphi的新命名:)

标签: delphi


【解决方案1】:

如果while not Terminated do 没有足够快地终止线程,那么每次迭代中完成的工作太多(即循环条件not Terminated 被检查得太少),或者你“不小心”放了一个很多代码这个循环之后。

当然,如果您有一个线程一遍又一遍地运行循环,直到终止,那么您应该执行while not Terminated do。通常一次迭代在短时间内完成(大约每秒 1 到 10000 次迭代?),因此经常检查循环条件(每秒 1 到 10000 次)。但是,如果您的线程不包含这样的循环,那么当然将整个 Execute 正文放入 while not Terminated do 将无济于事。

procedure TMyThread.Execute;
begin
  inherited;
    while not Terminated do
      ComputeTheNextTenDigitsOfPi; // Takes 100 ms.
end;

不好

procedure TMyThread.Execute;
begin
  inherited;
    while not Terminated do
      ComputeAVeryVeryLargeFractal; // Takes an hour.
                                    // And you will create the same fractal
                                    // over and over again.
end;

【讨论】:

    【解决方案2】:

    如果您必须终止作业 - 例如因为它被您无法控制的代码阻塞 - 然后考虑尝试将其完全包装在单独的可执行文件中,并将其作为子进程,并在需要停止时终止该进程。进程的隔离性比线程强得多。终止一个线程肯定会带来痛苦——如果被终止的线程在内存管理器或类似的地方持有锁怎么办?下次你尝试分配内存(或类似的)时,你的应用会死锁!

    【讨论】:

      【解决方案3】:

      CodeInChaos 在 cmets 中提供了一些很好的建议 - 在极少数情况下应该从外部终止线程。

      一些线程环境具有取消功能,您可以取消(而不是杀死)一个线程,它会在准备就绪时杀死自己。这允许线程设置自己的规则来确定何时可以安全终止。

      外部杀死的问题是目标线程可能有一个资源锁,现在永远不会被释放,导致潜在的死锁。或者,即使资源在线程退出时被释放,该资源中的数据也可能不再一致。

      要遵循的基本规则是所有线程都必须检查它们是否应该及时终止。换句话说,如果您正在等待工作,请在循环中几秒后超时并检查状态:

      do while not terminating:
          wait 2 seconds for work
          if not terminating and work available:
              do it
      

      一旦设置了terminating 标志,该特定线程将永远不会花费超过大约两秒的时间退出。

      而且,如果do it 是一个长时间运行的任务,您可能还需要定期检查其中是否也应该退出。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-23
        相关资源
        最近更新 更多