VB.NETの「非同期処理」を制する:UIを凍らせない、スマートな非同期プログラミングの極意
こんにちは。現場で「画面がフリーズして動かない……」という悲鳴を聞くたびに、私はいつもこう答えます。「それは、あなたが『同期』という名の呪縛に縛られているからです」と。
かつて、VB6や初期のVB.NETで非同期処理と言えば`BackgroundWorker`でした。しかし、今の時代、そんな複雑で扱いづらい道具に頼る必要はありません。`Async`と`Await`を使えば、コードは驚くほど直感的になり、UIはまるで呼吸をするように滑らかになります。
今日は、初心者から脱却したいあなたへ、VB.NETにおける非同期処理の「真髄」を授けましょう。
—
1. なぜ「同期」は悪なのか?(UIフリーズの正体)
プログラムを普通に書くと、コードは上から順に実行されます。これを「同期処理」と言います。
もし、ボタンを押した瞬間に「重いAPIを叩く」処理が走るとどうなるか?
1. CPUはAPIの返答を待つ。
2. その間、UIスレッド(画面を描画する役割)が完全に占領される。
3. Windowsは「このアプリは応答していません」と判断し、画面が白く固まる。
これを解決するのが「非同期処理」です。「重い仕事は別のスレッドに任せて、自分は画面の更新を続ける」。これが現代の開発の鉄則です。
—
2. Async/Await:魔法のキーワード
`Async`と`Await`は、まるで「ここでちょっと待ってるから、その間に画面の描画を続けておいてね」とCPUに伝えるための魔法の合図です。
基本の構文
‘ メソッドに Async をつけることで、非同期処理が可能になる
Public Async Function FetchDataAsync() As Task
‘ Await をつけると、その処理が終わるまで「一旦中断」してUIに制御を戻す
Dim result As String = Await Task.Run(Function()
‘ ここで重い処理(DBクエリやAPI通信)を行う
System.Threading.Thread.Sleep(3000) ‘ 擬似的な待ち時間
Return “データ取得完了”
End Function)
‘ 処理が戻ってきた後、UIスレッドでラベルなどを更新できる
Me.Label1.Text = result
End Function
—
3. 現場で使える「タイムアウト制御」と「複数タスクの待ち合わせ」
実務では、「APIがいつまでも返ってこない」という事態が必ず発生します。そんな時に役立つのが `CancellationTokenSource` です。
タイムアウト付き非同期処理のコード例
Public Async Sub OnButton_Click(sender As Object, e As EventArgs) Handles Button1.Click
‘ 3秒経ったら強制キャンセルするトークンを作成
Dim cts As New System.Threading.CancellationTokenSource(3000)
Try
‘ Task.Run にキャンセル用トークンを渡す
Dim result = Await Task.Run(Function() SomeHeavyWork(cts.Token), cts.Token)
MessageBox.Show(result)
Catch ex As OperationCanceledException
MessageBox.Show(“タイムアウトしました。通信環境を確認してください。”)
End Try
End Sub
複数のAPIを同時に叩く(Task.WhenAll)
もし、3つのAPIを順番に待っていたら時間がかかりすぎます。`Task.WhenAll`を使えば、並列に処理を開始し、全て終わるのを効率的に待つことができます。
‘ 複数のタスクをリスト化
Dim task1 = CallApiAsync(“https://api-a.com”)
Dim task2 = CallApiAsync(“https://api-b.com”)
‘ どちらも終わるのを待つ(並列処理!)
Await Task.WhenAll(task1, task2)
‘ 結果の取得
Dim result1 = task1.Result
Dim result2 = task2.Result
—
4. 陥りやすい罠:ここだけは注意して!
1. Async Subは「最後の手段」
ボタンイベント(`Handles …Click`)以外で `Async Sub` を使ってはいけません。戻り値がない非同期メソッドは、例外が発生した時にキャッチできず、アプリがクラッシュする原因になります。必ず `Async Function … As Task` を使いましょう。
2. UIスレッドをブロックしない
`Await` がついている行の前後では、UIスレッドが解放されています。しかし、`Await` を付けずに重い処理を記述すれば、結局UIはフリーズします。「すべての重い処理に `Await` を」と覚えておいてください。
—
最後に:一歩先のエンジニアへ
`BackgroundWorker` に別れを告げ、`Async/Await` を使いこなすことは、単にコードを綺麗にするだけではありません。「ユーザーの時間を奪わない」という、プロとしての誠実さを手に入れることでもあります。
最初は難しく感じるかもしれませんが、一度このリズムを掴めば、もう二度と「フリーズするプログラム」を書くことはなくなるはずです。
何か分からないことがあれば、いつでも聞いてください。あなたのコードが、より速く、より美しくなることを応援しています。それでは、次のステップでお会いしましょう!
