使用TThread.Resume有什么问题?

Jer*_*dge 14 delphi multithreading tthread deprecated

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

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

从那时起,Resume一直被弃用Start而不是使用.但是,Start只能从线程外部调用,并且不能从构造函数内部调用.

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

FMyThread := TMyThread.Create(SomeParamValue);
FMyThread.Start;
Run Code Online (Sandbox Code Playgroud)

问题:这个改变的原因是什么?我的意思是,使用Resume他们希望我们使用它的错误是什么Start

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

Del*_*ics 12

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

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

不受欢迎的人

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

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

出于令人惊讶的类似原因,调试器需要一种设施来直接挂起线程,而不管这些机制如何.

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

调试器的强大臂

调试器不能"注入"漂亮的,有礼貌的同步对象和机制来请求这些其他线程以一种其他线程(通过断点)的协调方式暂停自身.调试器别无选择,只能强调线程,这正是Suspend/Resume API的用途.

它们适用于需要停止线程的情况" 现在.无论你做什么我都不在乎,只要停下来! ".然后,然后再说" 好吧,你现在可以继续使用你以前做的任何事情,无论它是什么. "

表现良好的线程表现良好

显而易见的是,这不是一个行为良好的线程在正常操作中如何与其他线程交互(如果它希望保持"正常"操作状态而不会产生各种问题).在那些通常情况下一个线程非常应该关心的其他线程正在做的,并确保它不会干扰,使用适当的同步技术来协调与其他线程.

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

但是一旦启动了新线程,必须使用适当的同步技术实现与其他线程的后续同步,而不是暂停它的强力.

开始与暂停/恢复

因此,决定Suspend/Resume在通用线程类中没有真正的位置(实现调试器的人仍然可以直接调用Windows API),而是提供了更合适的"Start"机制.

希望显而易见的是,即使这个Start机制使用的是与之前使用的不推荐的Resume方法完全相同的API,但目的却完全不同.