Home New Help Edit

EurekaLogメモ

Suns & Moon Laboratory
Delphi memo

公式
EurekaLog


スレッドの例外を補足する

Delphi10.4 + EurekaLog7.9.5update5
やり方
  1. TThreadExを継承してスレッドを生成する
  2. TThreadEx.AutoHandleException=trueに設定(Thread.Create内)
  3. ツールバーのプロジェクト->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.

Home New Help Edit
2023-03-24 09:22:19 32400