こんにちは。現場で叩き上げられた、少しだけ経験豊富なエンジニアの先輩です。
VB.NETを触っていると、「重い処理を実行している間、画面がフリーズして動かなくなる」という壁に必ずぶつかりますよね。これ、初心者を卒業する最大の関門なんです。
今日は、その「フリーズ」を解消し、さらに「今の進捗状況をプログレスバーに表示する」という、プロの現場でも必須のテクニックを伝授します。これさえマスターすれば、君が書くアプリの品格は一気に上がります。
—
なぜ「フリーズ」するのか?― 魔法の言葉「Async/Await」の正体
まず前提として、UI(画面)は「メインスレッド」という一本の道の上で動いています。重い計算をその道でやると、画面の描画処理が待たされてしまい、結果として「応答なし」になります。
これを解決するのが `Async`(非同期)と `Await`(待機)です。
- Async: 「このメソッドは裏で動くよ」という宣言。
- Await: 「ここから先は裏で計算させるから、終わるまで一旦メインスレッドは解放してね」という指示。
これを使うと、裏で計算している間も画面はスルスル動き、ユーザーはプログレスバーを見ることができるのです。
—
現場で即戦力!IProgress(Of T) による進捗報告
単に非同期にするだけなら `Task.Run` で十分ですが、進捗率を伝えるには `IProgress(Of T)` インターフェースを使うのがVB.NETの正攻法です。これを使うと、「裏側で計算しているスレッドから、安全にUIスレッドへ値を渡す」という複雑な仕事を .NET が肩代わりしてくれます。
実践コード:プログレスバー連動サンプル
まずはフォームに `ProgressBar1` と `Button1` を配置してください。以下のコードを貼り付ければ、そのまま動きます。
Imports System.Threading
Public Class Form1
‘ ボタンが押されたら処理を開始する
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Button1.Enabled = False
ProgressBar1.Value = 0
‘ 1. 進捗報告用のインスタンスを作成
‘ Progress(Of Integer) は、数値を受け取ってUIを更新する箱です
Dim progressIndicator As New Progress(Of Integer)(Sub(percent)
ProgressBar1.Value = percent
End Sub)
‘ 2. 重い処理を非同期で実行(Awaitで完了を待つ)
Await Task.Run(Sub() DoHeavyWork(progressIndicator))
Button1.Enabled = True
MessageBox.Show(“処理が完了しました!”)
End Sub
‘ 3. バックグラウンドで動く重い処理
Private Sub DoHeavyWork(progress As IProgress(Of Integer))
For i As Integer = 1 To 100
‘ ここで時間のかかる処理をシミュレート
Thread.Sleep(50)
‘ 進捗を報告(UIスレッド側へ安全に値を送る)
If progress IsNot Nothing Then
progress.Report(i)
End If
Next
End Sub
End Class
—
押さえておくべき「3つのポイント」
1. `Async Sub` の罠
イベントハンドラ(ボタンクリック時など)は `Async Sub` でOKですが、それ以外のメソッドで非同期にする場合は `Async Function … As Task` にしましょう。`Sub` にすると例外をキャッチしづらくなるため、現場では `Task` を返すのが鉄則です。
2. UIスレッドのルール
VB.NETでは、「UI部品(ProgressBar等)は、それを作ったスレッドからしか触れない」という絶対的なルールがあります。`IProgress(Of T)` を使えば、このルールを意識せずに、バックグラウンド側から安全に値を送ることができます。もしこれを使わずに直接 `ProgressBar1.Value = …` と書くと、アプリはクラッシュします。注意してくださいね!
3. `Await` の位置
`Await` は、「そのメソッドが終わるまでここを一時停止する」というマークです。`Await` を書き忘れると、非同期処理が完了する前に次の行が実行されてしまい、バグの温床になります。
—
まとめ:ここをクリアすれば、もう初心者は卒業
最初は `Async/Await` という概念に戸惑うかもしれません。でも、「メインの道を塞がないように、裏道を用意してあげる」というイメージを持ってください。
- 重い処理は `Task.Run` で裏へ飛ばす。
- 状況報告は `IProgress(Of T)` でメインに戻す。
このパターンさえ覚えてしまえば、どんなに重いシステム開発でも怖くありません。マクロの記録から一歩踏み出し、自分だけの「動くアプリ」を作れるようになった君なら、きっと素晴らしいエンジニアになれます。
もし動かない箇所があれば、いつでも質問してください。コードの裏側にある「なぜそうするのか」を理解したとき、プログラミングはもっと楽しくなりますよ!
