Доступен ли обход цепочки ожидания Delphi 2009 в установках Windows 7? - PullRequest
9 голосов
/ 09 ноября 2010

Согласно «Что нового в Delphi 2009», есть новые функции отладчика, называемые «обход цепочки ожидания». В нем, в частности, говорится: «Была добавлена ​​функция обхода цепочки ожидания, чтобы помочь вам решить проблемы с конфликтами потоков или взаимоблокировками. Эта функция опирается на средство, добавленное в операционную систему Windows Vista, которое предоставляет отладчику информацию о состоянии ожидания потоков вашего приложения в форма цепочки ожидания. "

Delphi 2009 был выпущен, когда Windows Vista была текущей операционной системой. Исходя из моего опыта, большинство функций, представленных в Vista, также доступны в Windows 7. Однако я не вижу эту функцию нигде в моем Delphi 2009 с помощью установок Delphi XE (все в Windows 7).

Я ищу эту функцию на панели потоков отладчика.

  1. Я ищу обход цепи ожидания в правильном месте?

  2. Действительно ли эта функция доступна только в Windows Vista, а не в Windows 7?

Дэвид М дал хороший и четкий ответ, но я все еще не вижу столбец «Цепочка ожидания» на панели «Потоки». Вот некоторый код.

Основная форма:

unit Main;

interface

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

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure ThreadDone(Sender: TObject);
  end;

var
  Form1: TForm1;
  RanGenThread: TRandomizer;

implementation

uses LoadThread;

{$R *.dfm}

{ TForm1 }

procedure TForm1.ThreadDone(Sender: TObject);
begin
  RanGenThread.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
ListBox1.Sorted := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Thread: TLoader;
begin
ListBox1.Items.Clear;
ListBox1.Sorted := False;
RanGenThread := TRandomizer.Create(True);
RanGenThread.ArraySize := 1000;
Thread := TLoader.Create(True);
with Thread do
begin
  RanGenThread.WaitThread := Thread;
  FreeOnTerminate := True;
  OnTerminate := ThreadDone;
  WaitForThread := RanGenThread;
  //Use Start in Delphi 2010 or later, where Resume is deprecated
  Resume;
end;
RanGenThread.Resume;
end;

initialization
  Randomize;

end.

TRandomizer:

unit RanThread;

interface

uses
  Classes, Math, SyncObjs;

type
  TRandomizer = class(TThread)
  private
    { Private declarations }
    FArraySize: Integer;
  protected
    procedure Execute; override;
  public
    WaitThread: TThread;
    RandNumbers: array of Integer;
    property ArraySize: Integer read FArraySize write FArraySize;

  end;

implementation

uses Main;

procedure TRandomizer.Execute;
var
  i: Integer;
  LowNum, HighNum: Integer;
  RandNum: Integer;
begin
if FArraySize = 0 then
  begin
    Exit;
  end;
SetLength(RandNumbers, FArraySize);
LowNum := Low(RandNumbers);
HighNum := High(RandNumbers);
//initialize the array
for i := LowNum to HighNum do
  RandNumbers[i] := -1;
// generate the random order
for i := LowNum to HighNum do
  while True do
    begin
      RandNum := RandomRange(LowNum, HighNum + 1);
      if RandNumbers[RandNum] = -1 then
      begin
        RandNumbers[RandNum] := i + 1;
        break;
      end; // if
    end; // while
    WaitThread.WaitFor;
end;

end.

TLoader:

unit LoadThread;

interface

uses
  Classes, SyncObjs, Dialogs, SysUtils, RanThread;

type
  TLoader = class(TThread)
  private
    FWaitForThread: TRandomizer;
    procedure UpdateList;
    { Private declarations }
  protected
    procedure Execute; override;
  public
    property WaitForThread: TRandomizer
      read FWaitForThread write FWaitForThread;
  end;

implementation

uses Main;

procedure TLoader.UpdateList;
var
 i: Integer;
begin
for i := Low(FWaitForThread.RandNumbers) to
  High(FWaitForThread.RandNumbers) do
  Form1.ListBox1.Items.Add(IntToStr(FWaitForThread.RandNumbers[i]));
end;

procedure TLoader.Execute;
begin
if WaitForThread <> nil then
begin
  FWaitForThread.WaitFor;
  Synchronize(UpDateList)
end;
end;

end.

Согласно документу обхода цепочки ожидания, с которым связывался Дэвид М, WTC доступен для следующих объектов синхронизации:

  • ALPC
  • COM
  • Критические разделы
  • Мьютексы
  • SendMessage
  • Ожидание операций над процессами и потоками

Мой код ожидает потока, но это TThread, а не непосредственно нить. Этим вечером я изменю свой пример кода, чтобы он зашел в тупик при ожидании Mutex, и посмотрю, не приведет ли это к появлению столбца Wait Chain на панели Thread.

OK. Наконец-то нашел время для следующего теста. Создано приложение, которое стало владельцем Mutex при запуске. Создал рабочий поток, который использовал OpenMutex для получения дескриптора этого Mutex, а затем вызвал WaitForsingleObject (handle, INFINITE). Все еще нет столбца цепочки ожидания на панели потоков.

1 Ответ

17 голосов
/ 09 ноября 2010
  1. Да .Напишите программу с двумя потоками, которые тупиковые.На панели «Потоки» вы увидите, что правый столбец (помеченный как «Цепочка ожидания») скажет что-то вроде «Ожидание блокировки, удерживаемой потоком 12345».Я не совсем уверен в точной фразе, так как в моей текущей программе нет тупиков :) Если вы ее не видите, прокрутите вправо.Если столбец просто не существует, это очень странно - скажите, пожалуйста, в комментарии.

  2. Нет .Обход цепочки ожидания был представлен в Vista (и Server 2008) и также доступен в Windows 7. Это можно увидеть, прочитав документацию MSDN по обходу цепочки ожидания и рассмотрев некоторые основные функции , все комментарии в таблице внизу со словами «Минимально поддерживаемый клиент: Windows Vista».Было бы сказано, был ли он удален в более поздней версии Windows - то, как он сформулирован, точно так же, как и для любого количества других функций.Кроме того, коллега, использующий Windows 7 (у меня Vista), имеет эту функцию.

Редактировать: Я попробовал ваш пример кода в Delphi 2010 (у меня нет2009 боюсь) на моей висте машине.Я нажал Button1 и Button2, а затем переключился в представление Threads, не останавливая программу.На панели «Потоки» был столбец «Цепочка ожидания», в котором содержался текст для двух потоков, не относящихся к основному потоку: «Заблокированное ожидание потока 11968» или «14416».

Вот снимок экрана:

Wait chain screenshot

Так вот, что вы должны получить в IDE, если эта функция работает.

Когда вы попробуете это, вы получите другие столбцы, но не столбец ожидания цепочки?Если это так, я признаю, что я немного озадачен, и я думаю, что следующим шагом может стать контакт с Embarcadero или хотя бы публикация на одном из их форумов , вероятно на этом .Я посмотрел, какие разрешения требуются для работы функций цепочки ожидания, но кажется, что вам даже не нужно SE_DEBUG_NAME, если вы работаете с процессом, принадлежащим текущему пользователю.(Я не совсем уверен, что это правильная интерпретация документации, но ...)

Я не думаю, что ваша IDE работает с нечетными привилегиями или в режиме совместимости с XP, или что-то еще? Редактировать 4: Это ответ. См. Комментарий Кэри ниже, ярлык работал в режиме совместимости с XP.

Редактировать 2: Я думал, что сделаюпроверьте работоспособность и посмотрите, что написано в их справочном файле.Я не могу найти справку 2009 года в Интернете, но в справке 2010 года говорится « Wait Chain: (только для Windows Vista и 7) ».Здорово.Затем я посмотрел на справку XE и там написано: « Wait Chain: (только для Windows Vista) ».Очень странно.

Я подозреваю, что это ошибка документации, и она должна работать в Windows 7, потому что я также сталкивался с этим исправлением Delphi 2009 для цепочки ожидания, работающей в Windows 7 .Звучит довольно поддержано для меня!Нет никакого способа, конечно, они удалили бы функцию, подобную этой, в самой новой версии своего продукта для самой новой версии Windows ... есть?Даже если они используют версию, в которой, согласно документам, она работает.

Редактировать 3: Я попросил коллегу, использующего Windows 7, тоже попробовать пример кода.Вот что он получил:

Wait chain traversal on Windows 7

На данный момент я признаю, что я немного озадачен.Все, что я могу сказать, это то, что он работает с RAD Studio 2010 в Windows 7 и, насколько я могу судить, должен работать для вас.Если это не так, у меня больше нет предложений, кроме нескольких смутных идей, приведенных выше!

...