1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.StdCtrls;
type
TIsFreezeThread = class(TThread)
private
Wnd :hWnd;
Interval :integer;
WatchThread :THandle;
WatchDog :integer;
class procedure TimerProc(aWnd: hWnd; aMsg: UINT; idEvent: NativeUInt; dwTime: DWORD); stdcall; static;
protected
procedure Execute; override;
public
constructor Create(aInterval :integer);
destructor Destroy; override;
end;
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FreezeThread :TIsFreezeThread;
public
end;
var
Form1: TForm1;
implementation
uses jclDebug;
//=====================================================================================================================================================================================================
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
// Simule un traitement long
Sleep(5000);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
// Contrôle toutes les 3s
FreezeThread := TIsFreezeThread.Create(3000);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FreezeThread.Free;
end;
//=====================================================================================================================================================================================================
{ TIsFreezeThread }
constructor TIsFreezeThread.Create(aInterval :integer);
begin
inherited Create;
Interval := aInterval;
Wnd := AllocateHWnd(nil);
SetTimer(Wnd, NativeUInt(Self), Interval div 2, @TimerProc);
DuplicateHandle(GetCurrentProcess, GetCurrentThread, GetCurrentProcess, @WatchThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
end;
destructor TIsFreezeThread.Destroy;
begin
KillTimer(Wnd, NativeUInt(Self));
DeallocateHWnd(Wnd);
inherited;
end;
procedure TIsFreezeThread.Execute;
begin
var PrevDog := -1;
while not Terminated do
begin
if InterlockedExchange(PrevDog, WatchDog) = PrevDog then
begin
var Stack := TStringList.Create;
try
with JclCreateThreadStackTrace(FALSE, WatchThread) do
try
AddToStrings(Stack, TRUE, FALSE, FALSE, FALSE);
Stack.SaveToFile('d:\Stack.txt');
finally
Free;
end;
finally
Stack.Free;
end;
end;
Sleep(Interval);
end;
end;
class procedure TIsFreezeThread.TimerProc(aWnd: hWnd; aMsg: UINT; idEvent: NativeUInt; dwTime: DWORD);
begin
InterlockedIncrement(TIsFreezeThread(idEvent).WatchDog);
end;
end. |
Partager