eurekalog
*EurekaLogメモ [[index]] [[dev/delphi]] 公式 [[EurekaLog>https://www.eurekalog.com/]] #contents **スレッドの例外を補足する 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でスレッドの例外を受け取る>https://vogelbarsch.com/2021-04-05-141239/]] [[<1> スレッドオブジェクト (Delphi コンカレントプログラミング)>https://qiita.com/ht_deko/items/39da99a10202589e002c]] end.
2024-11-23 18:45:00 32400