今回は、VB.NETのDoEventsで進行状況を確認する方法についてご紹介します。
DoEventsとは
通常、VB.NETで時間のかかる処理を実行すると、フォームやボタンなどのユーザーインターフェースが応答しなくなることがあります。
これは、Windowsのメッセージキューに蓄積された再描画やクリックのイベントが処理されず、画面が“固まった”状態になるためです。
そこでApplication.DoEvents()を呼び出すと、蓄積されたイベントを強制的に処理し、UIが更新されるようになります。
このメソッドを使うことで、長時間処理中でもフォームを再描画したり、ユーザーからの操作を受け付けたりすることが可能になります。
DoEventsの基本的な使い方
DoEventsは主に、ループなどの時間のかかる処理の合間に呼び出します。
例えば、カウンターを回すような処理の途中でDoEventsを呼ぶことで、毎回のループ終了時にUIが更新されます。
以下では、ラベルを使って進捗状況を表示するコード例を示します。
1 2 3 4 5 6 7 8 9 10 |
For i As Integer = 1 To 100 ' 処理時間をシミュレート System.Threading.Thread.Sleep(50) ' ラベルに進捗状況を表示 LabelProgress.Text = $"進捗:{i}%" ' UIを更新し、フォームが固まらないようにする Application.DoEvents() Next |
進捗:1%
進捗:2%
…
進捗:100%
このようにループ内でDoEventsを呼び出すと、各ステップごとにラベルの表示が更新されます。
進捗状況を確認するための具体例
プログレスバーを使った視覚的な進捗表示
ラベル以外にも、ProgressBarコントロールを使って進捗状況をわかりやすく示す方法があります。
下記のコードでは、プログレスバーが0から最大値まで遷移し、各ステップでDoEventsを呼んでUIが更新されるようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
' プログレスバーの初期設定 ProgressBar1.Minimum = 0 ProgressBar1.Maximum = 100 For i As Integer = 0 To 100 ' 処理時間をシミュレート System.Threading.Thread.Sleep(30) ' プログレスバーの値を更新 ProgressBar1.Value = i ' UIイベントを処理し、画面が固まらないようにする Application.DoEvents() Next |
プログレスバーの値が0%から100%まで変化します
キャンセルボタンを使った中断処理
長い処理を実行している間に、ユーザーがキャンセルボタンをクリックして処理を中断できるようにする場合もあります。
このとき、キャンセル用のフラグを用意し、DoEventsでボタンのクリックイベントを取り込みながら処理を進めるようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
' グローバル変数としてキャンセルフラグを定義 Dim cancelRequested As Boolean = False ' キャンセルボタンのクリックイベント Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click cancelRequested = True End Sub ' 長時間処理を実行するメソッド Private Sub ExecuteLongProcess() ProgressBar1.Minimum = 0 ProgressBar1.Maximum = 100 For i As Integer = 0 To 100 ' キャンセルフラグが立っていたらループを抜ける If cancelRequested Then Exit For End If ' 処理時間をシミュレート System.Threading.Thread.Sleep(50) ' プログレスバーの値を更新 ProgressBar1.Value = i ' イベントを処理してUIを更新 Application.DoEvents() Next End Sub |
キャンセルボタンをクリックすると、プログレスバーの更新が途中で停止します
このように、DoEventsで定期的にメッセージを処理すれば、クリックやフォームの再描画といった操作を処理に反映できます。
注意点と代替手段
DoEventsを頻繁に呼び出すと、再入性の問題が起こりやすくなります。
ユーザーが同じ操作を連続で行うと、同じ処理が複数回呼ばれたり、予期せぬタイミングで処理が割り込まれたりする可能性があるためです。
また、各呼び出し時にすべてのメッセージを処理するため、パフォーマンスが低下するリスクもあります。
そこで、Taskやasync/await、BackgroundWorkerなどの非同期処理を活用し、UIスレッドとは別のスレッドで重い処理を進める方法が推奨される場合があります。
まとめ
DoEventsは、長い処理中でもUIの応答性を確保できる便利なメソッドです。
ただし、使い方を誤ると再入性やパフォーマンスの問題が発生するため、適切な箇所で呼び出すことが重要になります。
より複雑な処理では、非同期処理の導入も検討し、安全かつ快適なユーザー体験を提供することが望ましいです。