使用TThread.Resume有什么问题?

时间:2016-03-14 23:44:11

标签: multithreading delphi deprecated tthread

很久以前,当我开始使用Delphi中的线程时,我通过在构造函数的末尾调用TThread.Resume来创建线程,并且仍然如此:

constructor TMyThread.Create(const ASomeParam: String);
begin
  inherited Create(True);
  try
    FSomeParam:= ASomeParam;
    //Initialize some stuff here...
  finally
    Resume;
  end;
end;

从那时起,Resume已被弃用,转而使用Start。但是,Start只能从线程外部调用,并且不能在构造函数中调用。

我继续使用Resume设计我的线程,如上所示,虽然我知道它已被弃用 - 只是因为我不想从线程外部调用Start。我发现打电话有点麻烦:

FMyThread := TMyThread.Create(SomeParamValue);
FMyThread.Start;

问题:这次改变的原因是什么?我的意思是,使用Resume他们希望我们使用Start代替什么呢?

编辑在Sedat回答之后,我想这实际上取决于构造函数中线程实际开始执行的时间。

1 个答案:

答案 0 :(得分:12)

简短而精辟的答案是因为 TThread 类的作者并不信任开发人员阅读或理解文档。 :)

暂停和恢复线程只是非常有限数量的用例的合法操作。事实上,有限的数字基本上是"一个":调试器

不受欢迎

它被认为是不合需要的(至少可以说)是因为如果一个线程被挂起而(例如)它拥有某个其他同步对象(例如互斥锁或sempahore等)的锁定时会出现问题。

这些同步对象专门设计用于确保线程相对于访问共享资源的其他线程的安全操作,因此中断和干扰这些机制可能会导致问题。

调试器需要设施直接暂停一个线程而不管这些机制是否出于类似的原因。

例如,考虑一个断点涉及一个隐含的(或者你甚至可以说 ex plicit)" suspend"线程上的操作。如果调试器在到达断点时停止某个线程,那么它还必须准确地挂起该进程中的所有其他线程,否则它们将会提前竞争可能会干扰调试器可能要求的许多低级别任务的工作。然后呢。

调试器的强大臂

调试器无法注入"好的,有礼貌的同步对象和机制,要求这些其他线程以一种协调的方式暂停自己,其他线程已被毫不客气地暂停(通过断点)。调试器没有选择,但要强化线程,这正是Suspend / Resume API的用途。

它们适用于需要停止线程的情况" 现在。无论你在做什么,我都不在乎,只是停下来!"。然后,然后说" 好的,你现在可以随时随地继续,不管它是什么。"。

表现良好的线程表现良好

非常明显的是,一个行为良好的线程如何在正常操作中与其他线程交互(如果它希望保持"正常"操作的状态而不是创造各种各样的问题)。在这些正常情况下,非常 的线程应该关心其他线程正在做什么,并确保它不会干扰,使用适当的同步技术来共同与其他线程一致。

在这些情况下,恢复线程的合法用例同样简化为单一模式。也就是说,您已经创建并初始化了一个您不希望立即运行的线程,但是在某个其他线程的控制下,稍后某个时间点开始执行。

但是一旦新线程已经启动,那么必须使用那些正确的同步技术实现与其他线程的后续同步,暂停它的力量。

开始与暂停/恢复

因此决定暂停 / 恢复在通用线程类中没有实际位置(实现调试器的人仍然可以直接调用Windows API' s )而是一个更合适的"开始"提供了机制。

希望显而易见的是,即使这个 Start 机制使用的是与之前使用的弃用Resume方法完全相同的API,但目的却大相径庭。