Согласно «Что нового в Delphi 2009», есть новые функции отладчика, называемые «обход цепочки ожидания». В нем конкретно говорится: «Функция обхода цепочки ожидания была добавлена, чтобы помочь вам разрешить конфликты потоков или проблемы с взаимоблокировкой». Эта функция использует средство, добавленное в операционную систему Windows Vista, которое предоставляет информацию отладчику о состоянии ожидания потоков вашего приложения в форма цепочки ожидания ».
Delphi 2009 был выпущен, когда Windows Vista была текущей операционной системой. По моему опыту, большинство функций, представленных в Vista, также доступны в Windows 7. Однако я не вижу эту функцию в своих установках Delphi 2009 через Delphi XE (все в Windows 7).
Я ищу эту функцию на панели потоков отладчика.
Ищу ли я обход цепочки ожидания в правильном месте?
Действительно ли эта функция доступна только в 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 доступен для следующих объектов синхронизации:
Мой код ожидает в потоке, но это TThread, а не непосредственно собственный поток. Этим вечером я изменю свой пример кода так, чтобы он блокировался при ожидании Mutex, и посмотрите, приведет ли это к появлению столбца «Цепочка ожидания» на панели потоков.
OK. Наконец-то нашлось время для следующего теста. Создал приложение, которое стало владельцем Mutex при запуске. Создал рабочий поток, который использовал OpenMutex для получения дескриптора этого Mutex, а затем вызвал WaitForsingleObject (handle, INFINITE). По-прежнему нет столбца цепочки ожидания на панели потоков.