【问题标题】:TThread.resume is deprecated in Delphi-2010 what should be used in place?TThread.resume 在 Delphi-2010 中已弃用,应该在什么地方使用?
【发布时间】:2009-09-13 17:39:02
【问题描述】:

在我的多线程应用程序中

我使用 TThread.suspend 和 TThread.resume

自从将我的应用程序移至 Delphi 2010 后,我收到以下警告信息

[DCC 警告] xxx.pas(277): W1000 Symbol ‘Resume’ is deprecated

如果不推荐使用 Resume,应该使用什么?

编辑 1:

我使用 Resume 命令启动线程 - 因为它是在我终止线程之前将“CreateSuspended”设置为 True 和 Suspend 创建的。

编辑 2:

Here is a link the delphi 2010 manual

【问题讨论】:

    标签: delphi delphi-2010


    【解决方案1】:

    Charles 如果你读过 TThread 类的代码,你找到答案了吗。

       TThread = class  
       private type  
    
    ..
    ..
    ..   
       public  
         constructor Create(CreateSuspended: Boolean);  
         destructor Destroy; override;  
         procedure AfterConstruction; override;  
         // This function is not intended to be used for thread synchronization.  
         procedure Resume; deprecated;  
         // Use Start after creating a suspended thread.  
         procedure Start;  
         // This function is not intended to be used for thread synchronization.  
         procedure Suspend; deprecated;  
         procedure Terminate;  
    

    查看此链接RAD Studio 2010: Community pulse: The day after. (Part 2)

    编辑:

    如果需要同步线程,可以使用基于TMutex、TEvent和临界区的方案。

    再见。

    【讨论】:

    • 这很好,只是我想知道我们实际需要编写什么代码?
    • 链接无效。现在它的内容在windwings.wordpress.com/2009/08/28/…
    • 不是每个人都可以访问他们的 Delphi 安装中的 RTL 代码。
    【解决方案2】:

    使用 TThread.Start 代替 .Resume

    --编辑-- Start 当然只能与 Delphi 2010(以及以后,大概)一起使用来启动一个被创建为挂起的线程(您之前会使用 Resume)。

    不推荐使用 Resume/Suspend(或相应的 WinAPI 函数)进行线程同步。请参阅here 的讨论(看看 Barry Kelly 的 cmets)。

    【讨论】:

    • 不是答案,真的 - 使用 Suspend() 和 Resume() 进行“同步”已被弃用,没有任何替代。自 Delphi 2 以来,适当的同步对象就已经可用。现在是时候弃用这些构思不当的方法了。
    • @mghie - 同意,暂停/恢复不应用于同步,但问题中没有提到同步。而新的“开始”至少在某些情况下可以取代旧的“恢复”(参见 RRUZ 发布的 TThread 代码)。
    • 我同意Resume() 的说法。然而对于Suspend(),IMO 只有这个解释,即使它没有在问题中说明。
    • 只有在您不与(可能)使用旧版本 Delphi 的开发人员共享源代码时,开始才能替换简历。恕我直言,Suspend 应该已被弃用并 Resume 充分记录。例如,“Resume 旨在用于激活在最初挂起状态下创建的线程。Suspend 和 Resume 不应用于管理线程开始运行后的执行状态。更好的是,应该已修复 Suspend(如果它还没有)并且没有被弃用,但是一些体面的文档已经到位。
    • +1 三角洲。这是一种可悲、可悲的状况。什么是废话 TThread。
    【解决方案3】:

    Suspend 和 Resume 可能(或曾经)在 TThread 类中被破坏(如果您查看源代码,您会看到Suspend 方法直接且无条件地将布尔值设置为指示线程挂起状态,而不是更可靠地从线程句柄上的执行计数派生该状态。具有讽刺意味的是,Resume 方法确实使用这个更稳健的指示器来更新暂停状态布尔值)。

    这可能是它们被弃用的原因。这也是我实现自己的类来封装 Windows 线程的原因,该类具有更强大的挂起和恢复机制以及在线程完成后重新启动线程的能力。

    我不确定为什么它们的弃用据说与同步有关。挂起和恢复线程不一定与同步有关,尽管我可以看到它可能是怎样的。有趣的是,.NET 框架 Thread 类中的等效方法同样被标记为已过时。相同的 cmets w.r.t 同步出现在线程挂起/恢复的 Windows API 文档中。

    如果使用不推荐使用的方法让您感到紧张,并且您仍然希望暂停/恢复,您可以随时使用 Windows API 到 suspend and resume the thread by reference to it's handle。

    【讨论】:

    • 如果“暂停和恢复线程不一定与同步相关”,您能否添加一些您认为应该使用Suspend() 和Resume() 的信息?我也真的很想知道为什么一个线程必须重新启动。
    • 这里有一些关于暂停/恢复的讨论:forums.codegear.com/message.jspa?messageID=3466 特别是看看 Barry Kelly 的 cmets。最重要的是,您不应该接触 Suspend 或 WinAPI SuspendThread 函数,并且 Resume 本质上应该只用于启动创建的已暂停线程。暂停/恢复不应用于线程同步。
    • 一个错误恕我直言。暂停和恢复线程是合法的操作。这不是做某些事情的正确方法,但解释如何/何时正确使用某些东西是文档的用途。而不是弃用并希望人们简单地停止使用这些方法(依靠模糊的“不要使用这些方法进行同步”和谷歌来帮助人们理解为什么)他们应该有:1)修复了 Suspend 的实现 2)正确记录了方法的预期用途。然后由开发人员决定是否使用它们。
    • CodeGear/Embarcadero 弃用了 Suspend 但没有引入替代品,这真的很糟糕。
    • @James - 怎么搞错了?我说这是合法的。它是合法的一种情况是当您是调试器时。你用不同的词说完全相同的事情。缺少的是文档中对这一事实或潜在错误的具体示例的任何引用。当然,如果一个线程不拥有同步对象(直接或间接),那么您的死锁场景就完全无关紧要了。这不会改变您不应该通常使用暂停/恢复的事实,或者 为什么不这样做的原因仍然文档中没有解释我>。这就是我所说的。
    【解决方案4】:

    以防万一您只想摆脱编译器提示

    (1)启动线程时去掉编译器提示...

    替换

    MyThread := TMyThread.Create(True);
    MyThread.Resume;
    

    与

    MyThread := TMyThread.Create(True);
    MyThread.Start;
    

    (2)Stopping a Thread时去掉编译提示...

    替换

    MyThread.Suspend;
    MyThread.Terminate;
    

    与

    MyThread.Terminate;
    

    没什么大不了的。当心企图混淆。

    【讨论】:

      【解决方案5】:

      线程行为控制代码应该位于线程过程中。使用适当的同步对象和相应的 API 调用来暂停/恢复线程执行。从外面做是一种危险的做法。所以决定贬低它。

      【讨论】:

      • 同意。就目前而言,这是一种很好的感觉,但是每次自己编写它就像每次要平行停放它时都必须在汽车上焊接一些东西。像“可以暂停的工作线程”这样的基本服务至少应该是 TWorkerThread 的一部分,如果不在基本 TThread 本身中的话。
      【解决方案6】:

      使用

      Suspended := False; // Resume;
      

      或

      Start;
      

      【讨论】:

        【解决方案7】:

        您应该按如下方式创建线程:

        constructor TSignalThread.Create;
        begin
         // create event handle first!
          FEventHandle := CreateEvent(
                  {security}      nil,
                  {bManualReset}  true,
                  {bInitialState} false,
                  {name}          nil);
          FWaitTime := 10;
          inherited Create({CreateSuspended}false);
        end;
        

        这样就不需要调用 Start。

        请参阅 http://www.gerixsoft.com/blog/delphi/creating-threads 了解为什么此代码有效。

        【讨论】:

          【解决方案8】:

          @mghie(我知道有点晚了)

          以 madexcept 等为例。如果您的应用程序崩溃并且正在向用户显示错误报告,这意味着该对话框正在等待用户输入。如果发生崩溃是线程操作的结果(不一定是线程崩溃),如果您不暂停线程,则屏幕将充满错误报告对话框。

          示例 2:日志记录。出于任何特殊原因,我至少需要记录一些线程的执行状态。这包括当前的堆栈跟踪。现在,正如您(应该)知道的那样,您不能在线程运行时执行此操作,因为在您收集有关它的信息期间,线程一直在做一些事情,因此在您完成收集时,收集的信息将不一致。因此,您需要暂停线程。

          我可以继续讨论线程管理的实际示例。当然,这些不是您在日常编程中要做的事情,但至少我确信你们中的许多人正在使用的第一个示例,即使您不了解它的内部结构。调试器?再次,您使用它们。 但实际上,在所有这些情况下,都没有使用 TThread,因为工作是在线程句柄上完成的。因此,确实很难找到一个有效的 TThread 挂起用法示例。但总的来说,线程是另一回事。

          【讨论】:

            猜你喜欢
            • 2016-10-14
            • 1970-01-01
            • 2019-07-21
            • 2013-09-01
            • 1970-01-01
            • 2014-01-09
            • 1970-01-01
            • 2020-07-16
            相关资源
            最近更新 更多