【问题标题】:Delphi IDE hangs when I create a thread创建线程时,Delphi IDE 挂起
【发布时间】:2015-07-21 10:51:06
【问题描述】:

我有一个问题,即当我运行线程时,Delphi (2010) IDE 和程序在调试期间都挂起。 两个窗口都没有响应。当我终止程序时,IDE 再次工作。

花了一些时间,我不得不删除我的程序片段,我发现了问题。 它是由 VirtualStringTree 引起的。

因此,如果我只在表单上放置空的 VirtualStringTree (v. 5.5.3),一个按钮在执行过程中仅使用“Sleep(2000)”执行 TThread 并在调试器下运行此类程序,它会挂起(通常在第一次单击时)。当我删除 VST 时,它可以工作。 我还注意到 Windows 报告服务已启动,但我在 Windows 事件日志中没有发现任何内容。

有人知道这怎么可能吗?

这里有完整的源代码

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, VirtualTrees, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    VirtualStringTree1: TVirtualStringTree;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
  TTestThread = class(TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TTestThread }

procedure TTestThread.Execute;
begin
  FreeOnTerminate:=True;

  Sleep(2000);
end;

{ TForm }    

procedure TForm1.Button1Click(Sender: TObject);
begin
  TTestThread.Create(False);
end;

end.

编辑:
我也尝试过调试 Delphi 进程。我从第二个连接到第一个 IDE。当我单击按钮启动线程时,两个 IDE 都挂起。所以我尝试了我也安装的 Delphi 7。那行得通。它停留在 ntdll.NtWaitForMultipleObjects、KERNELBASE.WaitForMultipleObjectsEx、USER32.MsgWaitForMultipleObjects 某处的循环中。

我已经完全重新安装了 Delphi,没有任何变化。它也可能与 VirtualStringTree 源代码中的这一行有关:“WaitForSingleObject(WorkEvent, INFINITE);”。当我删除它时,它不会冻结。但我认为那里是必要的。

最后我安装了 Delphi XE 并且工作正常。很神秘。

【问题讨论】:

  • 不清楚上下文是什么。设计时包。在调试器下运行的可执行文件?或者是其他东西。请给出精确的重现步骤。
  • 我稍微修改了一下。是的,它可以在调试器下执行。只需一个 VirtualStringTree 和一个按钮即可运行任何 TThread。
  • 能否附上一个小程序的完整源代码来重现这个? (因为它看起来像一个小程序会重现它......)
  • 运行 IDE 的两个副本,一个调试另一个。用它来找出它挂在哪里。

标签: multithreading delphi debugging delphi-2010 virtualtreeview


【解决方案1】:

TTestThread 在您的代码中是 TThread 的后代,但它仍然需要变量声明和正确的构造函数调用。

var
  MyThread: TTestThread;

实例化它的正确调用是

MyThread := TTestThread.Create(False); 

而不是像在按钮单击事件中那样尝试调用构造函数。

祝你好运,玩得开心。

RP

【讨论】:

  • 感谢您的关注,但这不是导致 IDE 和程序挂起的问题。我通常使用变量,但测试用例不需要。是否使用变量没有区别,它不会引起任何问题,只是没有保存在变量中。
  • 事实上@Radical,如果你确实按照你的建议添加了变量(假设是本地的),那么编译器会生成一个提示,告诉你分配的值没有被使用。此外,编译器不会生成设置变量的代码——因为没有意义。
  • @Craig - 如果编译器正在生成该提示,那么很可能仍在直接调用基类(调用 TTestThread 而不是 MyThread)。反相
  • @Radical 在我看来,您不理解我的评论和/或您误解了一些 OO 原则。 1) 变量声明对对象的构造方式具有零影响TTestThread.Create(False); 创建TTestThread 的实例,因为这是调用构造函数的类的名称。 2) 是的,如果没有在 TTestThread 上重新实现,将调用 Create(Boolean) 的父/基实现,但这不会改变构造的对象将是 @987654327 的事实@ 实例。 您可以将对象构造视为 2 个步骤:
  • (续)a) 实例化对象。 b) 在新对象上调用构造方法。 3) 现在该对象存在,将新实例的引用分配给MyThread 是一个完全独立的步骤。 (将MyThread := TTestThread.Create(...) 视为TTestThread.Create(...) --> MyThread 可能会有所帮助)4) 如果您在超出范围之前没有实际使用MyThread,则此分配毫无意义。
猜你喜欢
  • 1970-01-01
  • 2015-09-05
  • 2014-06-18
  • 2013-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多