【入門編】上級プロフェッショナル向け:VB.NETでのAsync/AwaitとIProgress(Of T)を用いた高度な非同期処理:UIのフリーズを防ぐ進捗率プログレスバーの安全な実装 – Visual Basic (VB / VB.NET)解析バイブル

スポンサーリンク

VB.NETの極み:Async/AwaitとIProgressでUIフリーズを撲滅する「プロの非同期処理」

こんにちは。現場の最前線でコードと向き合い続けてきたエンジニアとして、今日は皆さんに「VB.NETで最も避けるべき罠」と、それを華麗に回避する「プロの作法」を伝授します。

多くのVB.NET開発者が遭遇する壁、それが「重い処理によるUIのフリーズ(応答なし)」です。ボタンを押した瞬間、画面が白くなりマウスカーソルが回り始める……あれは、UIスレッドという「画面を描画する専属の係員」に、重い計算を押し付けていることが原因です。

今日は、`Async/Await`と`IProgress(Of T)`を使って、ユーザーを待たせず、かつコードも美しい「モダンな非同期アーキテクチャ」を構築する方法を解説します。

1. なぜ「DoEvents」を使ってはいけないのか?

昔ながらのVB.NET開発者は、重い処理の中に `Application.DoEvents()` を挿入してフリーズを回避しようとします。しかし、これは「禁じ手」です。

  • なぜダメか?:処理の再入(Re-entrancy)を引き起こし、意図しないタイミングでボタンが二重クリックされたり、アプリケーションが不安定になるリスクが高いからです。

現代のVB.NETでは、「非同期の作法」に従うのが正解です。

2. 核心のツール:Async/AwaitとIProgress(Of T)

非同期処理を完璧に制御するために、以下の2つをセットで使います。

1. Async/Await: 「ここから先は別のスレッドで動くぞ」と宣言し、終わるまでUIをブロックせずに待つための魔法の呪文。
2. IProgress(Of T): 「別スレッドで計算しているけど、進捗状況だけは安全にUIに教えてね」という、スレッド間通信の架け橋。

実装コード:安全でスマートな進捗報告

以下のコードは、バックグラウンドで重い処理を行いながら、プログレスバーを更新する現場レベルのテンプレートです。

Imports System.Threading
Imports System.Threading.Tasks

Public Class MainForm

‘ ボタンクリックで処理を開始
Private Async Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
btnStart.Enabled = False
ProgressBar1.Value = 0

‘ 1. 進捗報告用オブジェクトの生成
‘ Progress(Of T)は、UIスレッドでイベントを拾うように自動設計されています
Dim progress As New Progress(Of Integer)(Sub(percent)
ProgressBar1.Value = percent
End Sub)

‘ 2. 非同期メソッドを呼び出す(Awaitで待つが、UIはフリーズしない)
Await Task.Run(Sub() DoHeavyWork(progress))

btnStart.Enabled = True
MessageBox.Show(“処理が完了しました!”)
End Sub

‘ 重い処理(バックグラウンドスレッドで実行される)
Private Sub DoHeavyWork(progress As IProgress(Of Integer))
For i As Integer = 1 To 100
‘ ここで時間のかかる処理をシミュレート
Thread.Sleep(50)

‘ 3. 進捗をメインUIへ報告
progress.Report(i)
Next
End Sub

End Class

3. コードの読み解き:ここがポイント!

  • `Async Sub`: イベントハンドラ(クリックなど)には `Async Sub` を使います。これを使うことで、`Await` を記述できるようになります。
  • `Task.Run`: これにより、メインのUIスレッドから処理を切り離し、別のワーカー・スレッドに投げ込みます。
  • `Progress(Of Integer)`: これが非常に賢い点です。`Progress` クラスをUIスレッドで生成すると、内部的に `SynchronizationContext` をキャプチャします。その結果、バックグラウンドから `Report` を呼び出しても、自動的にUIスレッドに同期して進捗更新を行ってくれます。つまり、面倒な `Invoke` や `BeginInvoke` を書く必要は一切ありません。

4. プロとして陥りやすいエラーを防ぐ

最後に、現場でよく見る「やってはいけないこと」を2つだけ伝えます。

1. バックグラウンドから直接UIをいじらない:
`DoHeavyWork` 内で `ProgressBar1.Value = i` と書くのはNGです。「スレッド間操作の例外」が発生します。必ず `IProgress(Of T)` を経由してください。
2. Awaitを忘れない:
`Async` メソッドを呼び出す際に `Await` を忘れると、処理が終わるのを待たずに次のコードが実行されてしまいます。コードの意図が崩壊するので注意しましょう。

最後に:エンジニアとしてのステップアップ

非同期処理をマスターすると、あなたのVB.NETプログラムは「カクカク動くおもちゃ」から「プロフェッショナルなツール」へと進化します。

「UIスレッドを解放する」。これが自動化エンジニアの第一歩であり、究極の最適化です。ぜひ、今担当しているコードにこのパターンを組み込んでみてください。世界が変わるはずです。

もし分からないことがあれば、いつでも聞いてくださいね。応援しています!

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