EurekaLogメモ
Suns & Moon Laboratory
Delphi memo
公式
EurekaLog
スレッドの例外を補足する
Delphi10.4 + EurekaLog7.9.5update5
やり方
- TThreadExを継承してスレッドを生成する
- TThreadEx.AutoHandleException=trueに設定(Thread.Create内)
- ツールバーのプロジェクト->EurekaLog options...->Features->Multi-threading->Include stacks of EurekaLog-enabled threads=trueに設定
以下サンプルソース
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, Windows,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Controls.Presentation, FMX.StdCtrls,
IxSimpleThread;
type
TForm1 = class(TForm)
Button1: TButton;
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ private 宣言 }
thread_runner: TIxThreadRunner;
public
{ public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
procedure TForm1.FormCreate(Sender: TObject);
begin
thread_runner := TIxThreadRunner.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
thread_runner.Free;
end;
end.
スレッドの終了処理を実装したらちょっと長くなってしまった。
EurecaLogの動作確認用なので汎用性はちょっと無い。
unit IxSimpleThread;
interface
uses
System.Classes, System.Types, System.SysUtils, System.SyncObjs,
EBase; // ★EurekaLogのTThreadExはEBaseで宣言
{
Delphi10.4 + EurekaLog7.9.5update5
EurekaLogのオプションを設定
プロジェクト
▼
EurecaLog options...
▼
Features
▼
Multi-threading
▼
Include stacks of EurekaLog-enabled threadsをチェック
}
{
TThreadEx(EurekaLogの例外対応スレッド)に終了処理用イベント追加
このクラスを継承したクラスで生成する
}
type
TIxThreadEx = class(TThreadEx) // ★EurekaLog対応するにはTThreadExを継承する
protected
procedure Execute; override;
public
Event: TEvent;
constructor Create;
procedure OnTerminateExecute(Sender: TObject);
end;
{
スレッドの起動と修了を行う
}
type
TIxThreadRunner = class(TObject)
protected
thread: TIxThreadEx;
Event: TEvent;
public
constructor Create; overload;
destructor Free; overload;
end;
implementation
uses Windows;
// ==========================================================================
{ IxSimpleThread }
// ==========================================================================
// ----------------------------------------------------------------
// Create
// ----------------------------------------------------------------
constructor TIxThreadEx.Create;
begin
// EurekaLog
AutoHandleException := true; // ★EurekaLogで例外を検出するための設定
// 終了処理
OnTerminate := OnTerminateExecute; // 終了時のイベントを登録
FreeOnTerminate := true; // true:終了時自動解放する
// スレッドの生成
inherited Create(true); // true:生成時停止 false:生成時即実行
end;
// ----------------------------------------------------------------
// OnTerminateExecute(Sender
// ----------------------------------------------------------------
procedure TIxThreadEx.OnTerminateExecute(Sender: TObject);
begin
// 終了通知
OutputDebugString('スレッド OnterminateExecute');
Event.SetEvent;
end;
// ----------------------------------------------------------------
// Execute
// ----------------------------------------------------------------
// 約3秒後に例外を発生させる
procedure TIxThreadEx.Execute;
var
cnt: integer;
begin
cnt := 3000;
while not Terminated do
begin
sleep(50);
if cnt >= 0 then
dec(cnt, 50);
if cnt = 0 then
begin
cnt := -1;
{$IF false}
// ----------------------------------------------
// ----------------------------------------------
// 例外発生時
// 例外発生→OnTerminate→例外ダイアログ
raise Exception.Create('スレッド エラー発生');
{$ENDIF}
{$IF false}
// ----------------------------------------------
// 例外をfinallyで処理した場合
// ----------------------------------------------
// 例外発生時
// 例外発生→finally→OnTerminate→例外ダイアログ
try
raise Exception.Create('スレッド エラー発生');
finally
OutputDebugString('スレッド finally');
end;
{$ENDIF}
{$IF false}
// ----------------------------------------------
// 例外をexceptでサイレント処理した場合
// ----------------------------------------------
// 例外発生時
// 例外発生→exceptでサイレント→例外ダイアログは出ない
// (謎)何事も無かったかに見えるが、Execute抜ける前にEvent.SetEventしないとMemoryLeakする
try
raise Exception.Create('スレッド エラー発生');
except
OutputDebugString('スレッド except');
end;
{$ENDIF}
end;
end;
Event.SetEvent;
OutputDebugString('スレッド Execute終了');
end;
// ==========================================================================
{ TIxThreadRunner }
// ==========================================================================
// ----------------------------------------------------------------
// Create
// ----------------------------------------------------------------
constructor TIxThreadRunner.Create;
begin
Event := TEvent.Create;
thread := TIxThreadEx.Create;
thread.Event := Event;
Event.ResetEvent;
thread.Start;
end;
// ----------------------------------------------------------------
// Free
// ----------------------------------------------------------------
destructor TIxThreadRunner.Free;
begin
// スレッドの終了
// スレッドが例外で終了していた場合は、Terminate呼び出さない
if Event.WaitFor(0) <> wrSignaled then
thread.Terminate; // 通常の終了処理。WaitForがタイムアウトするのでこれが呼ばれる
{$IF false}
// スレッド終了待ち処理
if Event.WaitFor(3000) = wrSignaled then
OutputDebugString('WaitFor スレッド終了')
else
OutputDebugString('WaitFor スレッド終了待ち タイムアウト');
{$ENDIF}
Event.Free;
end;
end.
参考
EurekaLogでスレッドの例外を受け取る
<1> スレッドオブジェクト (Delphi コンカレントプログラミング)
end.
2024-08-14 11:00:26 32400