【入門編】上級プロフェッショナル向け:VB.NETでのExceptionDispatchInfoを活用したスレッド間例外の正確な再スローとエラー伝播 – Visual Basic (VB / VB.NET)解析バイブル

スポンサーリンク

スタックトレースを殺すな:VB.NETで例外を「完全な形」で運ぶための極意

こんにちは。現場の最前線でコードと格闘している皆さん。
今日は、VB.NETにおける「例外処理」の、まさに深淵に触れる話をしましょう。

多くの開発者が、非同期処理やマルチスレッドで例外が発生した際、安易に `Throw ex` を書いてスタックトレースを台無しにしてしまっています。これでは「どこで何が起きたのか」という真実が消滅し、デバッグは迷宮入りです。

今日は、プロフェッショナルとして「例外の魂(スタックトレース)を維持したまま、別スレッドから例外を運ぶ」ための最強の武器、`ExceptionDispatchInfo` を伝授します。

1. なぜ「Throw ex」は罪深いのか

まずは、多くの人がやってしまいがちな「アンチパターン」を見てください。

Try
‘ 重い処理や非同期タスク
Throw New InvalidOperationException(“致命的なエラーが発生しました”)
Catch ex As Exception
‘ ここで Throw ex をすると…
Throw ex ‘ 【警告】ここで元のスタックトレースがリセットされます!
End Try

`Throw ex` を行うと、VB.NETのランタイムは「現在の場所」を新しい起点として例外を再構築します。つまり、エラーが発生した真の箇所(深層)の情報が消え、Catchした場所が「エラーの発生源」として塗り替えられてしまうのです。これでは、運用保守の現場ではお手上げです。

2. 救世主:ExceptionDispatchInfo

.NET Framework 4.5から導入された `System.Runtime.ExceptionServices.ExceptionDispatchInfo` は、例外の「状態」をスナップショットとしてキャプチャし、後から好きな場所で再スローできる強力なクラスです。

これを使えば、非同期タスク内で起きた悲劇を、メインスレッドへ「当時のまま」届けることができます。

実装例:例外の完全保存と転送

Imports System.Runtime.ExceptionServices
Imports System.Threading.Tasks

Public Class ExceptionHandlerSample

‘ 例外をキャプチャして保持する変数
Private _capturedException As ExceptionDispatchInfo

Public Async Sub RunTask()
Try
‘ 意図的にエラーを起こす非同期タスク
Await Task.Run(Sub()
Throw New ApplicationException(“深層で発生した重要なエラー”)
End Sub)
Catch ex As Exception
‘ ここがポイント!
‘ 例外が発生した瞬間のスタックトレースを丸ごと保存する
_capturedException = ExceptionDispatchInfo.Capture(ex)
End Try

‘ ここでメインスレッドに処理を戻し、保存した例外を再スローする
If _capturedException IsNot Nothing Then
‘ 元のスタックトレースを保持したまま例外が投げられる!
_capturedException.Throw()
End If
End Sub
End Class

このコードが優れている理由

1. スタックトレースの保存: `ExceptionDispatchInfo.Capture(ex)` が、例外オブジェクトの現在のコンテキストをそのまま凍結保存します。
2. 正確な伝播: `.Throw()` を呼ぶと、ランタイムはあたかも「最初からそこで例外が起きたかのように」振る舞います。ログ出力時の行番号が正確に追えるため、原因特定までの時間が劇的に短縮されます。

3. なぜ今、これを理解する必要があるのか

「マクロの記録」から卒業し、本格的な業務システムを構築するフェーズに入った皆さんにとって、「エラーの可視化」は設計と同等に重要です。

  • 保守性の向上: 現場でエラーが起きたとき、ログに「発生源が不明」と書かれていて絶望したことはありませんか? `ExceptionDispatchInfo` を使えば、その絶望を解消できます。
  • 非同期制御の掌握: UIスレッドをフリーズさせないための非同期処理は必須ですが、そこで例外を握りつぶしてしまうと、システムは「静かな死」を迎えます。正しく例外を伝えることは、システムの健全性を保つための責任です。

プロからのアドバイス:ここをクリアすれば「中級者」です

VB.NETは古い言語だと言われることもありますが、その裏側にある .NET の強力なランタイム機能は、最新の言語と全く遜色がありません。

  • 基本: `Try…Catch` で囲む。
  • 発展: `Throw`(例外をそのまま投げる)を使う。
  • 極致: `ExceptionDispatchInfo` で例外のライフサイクルを制御する。

このステップをマスターしたとき、あなたは単なる「コードを書く人」から、「システムの挙動を制御するエンジニア」へと進化しています。

難しい概念かもしれませんが、まずは小さな非同期処理の中で `ExceptionDispatchInfo` を試してみてください。ログ出力の質が劇的に変わることに驚くはずです。

さあ、次はどんな壁を突破しましょうか? 応援していますよ。

タイトルとURLをコピーしました