Delphi IDE зависает, когда я создаю поток

У меня проблема в том, что Delphi (2010) IDE и программа зависают во время отладки, когда я запускаю поток. Оба окна не отвечают. Когда я убиваю программу, IDE снова работает.

Потребовалось время, мне пришлось удалить куски моей программы, и я нашел проблему. Это вызвано VirtualStringTree.

Поэтому, если я помещаю в форму просто пустой VirtualStringTree (v. 5.5.3), одну кнопку для выполнения TThread с помощью «Сон (2000)» в процедуре «Выполнение» и запускаю такую ​​программу под отладчиком, она зависает (обычно при первом нажатии). Когда я удаляю 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.

EDIT:
Я также пытался отладить процесс Delphi. Я подключился со второго к первому IDE. Когда я нажимаю кнопку, чтобы запустить поток, обе IDE зависают. Итак, я попробовал Delphi 7, который я также установил. Это сработало. Он остается в цикле где-то в ntdll.NtWaitForMultipleObjects, KERNELBASE.WaitForMultipleObjectsEx, USER32.MsgWaitForMultipleObjects.

Я полностью переустановил Delphi, без изменений. Это также может быть связано с этой строкой в ​​исходном коде VirtualStringTree: «WaitForSingleObject(WorkEvent, INFINITE);». Когда я его удаляю, он не замерзает. Но я думаю, что это необходимо там.

Наконец я установил Delphi XE, и все работает правильно. Это загадочно.


person smooty86    schedule 21.07.2015    source источник
comment
Непонятно какой контекст. Пакет времени на разработку. Исполняемый файл работает под отладчиком? Или что-то другое. Пожалуйста, укажите точные шаги для воспроизведения.   -  person David Heffernan    schedule 21.07.2015
comment
Я его немного модифицировал. Да, он выполняется под отладчиком. Всего одно VirtualStringTree и одна кнопка для запуска любого TThread.   -  person smooty86    schedule 21.07.2015
comment
Можете ли вы включить полный исходный код небольшой программы, которая воспроизводит это? (Поскольку похоже, что крошечная программа воспроизведет его...)   -  person David    schedule 21.07.2015
comment
Запустите две копии IDE, одну для отладки другой. Используйте это, чтобы узнать, где он висит.   -  person Rob Kennedy    schedule 21.07.2015


Ответы (1)


TTestThread является потомком TThread в вашем коде, но ему по-прежнему требуется объявление переменной и правильный вызов конструктора.

var
  MyThread: TTestThread;

Правильный вызов для создания экземпляра был бы

MyThread := TTestThread.Create(False); 

вместо того, чтобы пытаться вызвать конструктор, как в событии нажатия кнопки.

Удачи и приятного времяпровождения.

RP

person RadicalPumpkin    schedule 22.07.2015
comment
Спасибо за внимание, но это не та проблема, из-за которой IDE и программа зависают. Обычно я использую переменные, но в тестовом случае это не обязательно. Нет никакой разницы, используете вы переменную или нет, это не вызывает никаких проблем, просто не хранится в переменной. - person smooty86; 22.07.2015
comment
На самом деле @Radical, если вы добавите переменную, как вы предлагаете (при условии, что она локальна), тогда компилятор сгенерирует подсказку, сообщающую вам, что назначенное значение не используется. Кроме того, компилятор не будет генерировать код для установки переменной - потому что в этом нет смысла. - person Disillusioned; 23.07.2015
comment
@Craig - если компилятор генерирует эту подсказку, то, вероятно, базовый класс все еще вызывается напрямую (вызывая TTestThread, а не MyThread). РП - person RadicalPumpkin; 27.07.2015
comment
@Radical Мне кажется, вы не поняли мой комментарий и/или неправильно понимаете некоторые принципы ООП. 1) Объявление переменной не влияет на то, как создается объект. TTestThread.Create(False); создает экземпляр TTestThread, потому что это имя класса, для которого вызывается конструктор. 2) Да, родительская/базовая реализация Create(Boolean) будет вызываться, если не будет повторно реализована в TTestThread, но это не меняет того факта, что созданный объект будет экземпляром TTestThread. Создание объекта можно представить как два шага: - person Disillusioned; 27.07.2015
comment
(продолжение) a) создание экземпляра объекта. б) вызвать метод конструктора для нового объекта. 3) Теперь, когда этот объект существует, совершенно отдельным шагом является назначение ссылки на новый экземпляр для MyThread. (Может помочь думать о MyThread := TTestThread.Create(...) как о TTestThread.Create(...) --> MyThread) 4) Это присвоение бессмысленно, если вы фактически не используете MyThread до того, как оно выйдет за рамки. - person Disillusioned; 27.07.2015