【入門編】Windows FormsのProgressBarを用いた不確定プロパティ(Marquee)のスマートな制御:処理時間が予測できないバッチ処理中のUI演出手法 – Visual Basic (VB / VB.NET)解析バイブル

スポンサーリンク
スポンサーリンク

「フリーズ」という名の絶望を回避せよ:ProgressBar(Marquee)を使いこなす、真のUI設計術

こんにちは。現場で数々の複雑なシステムを設計してきた、あなたのエンジニア仲間です。

プログラミングを学び始め、マクロの記録から一歩踏み出して「自分でツールを作ってみよう!」と意気込んでいる時、誰もが一度はぶつかる壁があります。それは、「重い処理を実行した瞬間に、アプリが『応答なし』になって固まってしまう」という現象です。

せっかく作った便利なツールが、実行中に真っ白になって動かなくなったら、ユーザーは不安になります。「壊れたのかな?」「止まってしまったのかな?」と。

今日は、そんな「ユーザーの不安」を「安心感」に変えるための魔法、ProgressBarの`Marquee`(マーキー)スタイルを使った、スマートなUI制御術を伝授します。ここをマスターすれば、あなたの作るアプリケーションの「格」は、一気にプロの領域へと引き上げられます。

1. なぜプログレスバーは「止まって」しまうのか?

まず、技術的な本質を理解しましょう。ここが「なんとなく動いた」で終わる人と、「仕組みを理解して制御できる」人の決定的な差になります。

Windows Formsアプリケーションには、「UIスレッド」と呼ばれる、画面の描画やマウス操作を受け付ける専用の通り道(スレッド)があります。

  • 正常な状態: UIスレッドが「画面を描画せよ」「マウスが動いたぞ」という命令を、高速にぐるぐると処理し続けています。
  • フリーズ状態: UIスレッドが「重い計算(バッチ処理)」に没頭してしまい、画面を描画するための命令を無視してしまっている状態です。

どんなにプログレスバーを「動け!」と命令しても、その命令を受け取る担当者(UIスレッド)が計算に忙殺されていれば、バーはピクリとも動きません。これが「フリーズ」の正体です。

2. 「進捗率」がわからない時の救世主:Marqueeスタイル

通常、プログレスバーは「今、全体の何%終わったか」を示すために使います。しかし、実務では「あと何分かかるか全く予測できない処理」(例:大量のファイルを検索する、ネットワーク越しにデータを集めるなど)が山ほどあります。

そんな時に使うのが、`ProgressBar`の`Style`プロパティを `Marquee` に設定する手法です。

Marqueeスタイルの特徴

  • 進捗率(Value)を必要としない: 0%から100%へ進むのではなく、光の筋がバーの中を永遠に走り続けます。
  • 「動いていること」の証明: ユーザーに対して「アプリは死んでいない。今、裏で一生懸命動いているよ」という視覚的なメッセージを送り続けます。

3. 【実践】フリーズさせずにMarqueeを動かす「黄金のコード」

では、実際にどう書くべきか。
かつては「BackgroundWorker」という仕組みが主流でしたが、現代のVB.NETにおいて最もスマートで、エラーを避けやすいのは `Async / Await`(非同期処理) を使う方法です。

以下のコードは、ボタンを押すと「予測不能な重い処理」が始まり、その間だけプログレスバーがアニメーションする、お手本のような実装です。

''' <summary>
''' フォームのクラス定義
''' </summary>
Public Class Form1

    ''' <summary>
    ''' 実行ボタンがクリックされた時のイベント
    ''' Asyncキーワードを付けることで、このメソッド内で「待機(Await)」が可能になります。
    ''' </summary>
    Private Async Sub btnStart_Click(sender As Object, e) Handles btnStart.Click
        
        ' 1. UIの準備
        ' ユーザーが二重にボタンを押さないよう、ボタンを無効化します
        btnStart.Enabled = False
        lblStatus.Text = "処理を実行中です... しばらくお待ちください。"

        ' 2. プログレスバーを「Marqueeモード」に設定
        ' これにより、進捗率に関わらずアニメーションが始まります
        progressBar1.Style = ProgressBarStyle.Marquee
        ' アニメーションの速度を調整したい場合は、MarqueeAnimationSpeedプロパティを使います(※)
        ' progressBar1.MarqueeAnimationSpeed = 30 

        Try
            ' 3. 【重要】重い処理を「別スレッド」で実行する
            ' Task.Run を使うことで、UIスレッドを解放し、計算を裏側(バックグラウンド)に投げます。
            ' Await を使うことで、「処理が終わるまで待つが、その間UIスレッドは自由にしておいてね」と指示します。
            Await Task.Run(Sub()
                               PerformHeavyTask()
                           End Sub)

            ' 4. 完了後の処理
            lblStatus.Text = "処理が正常に完了しました!"
            MessageBox.Show("すべてのタスクが終了しました。", "完了", MessageBoxButtons.OK, MessageBoxIcon.Information)

        Catch ex As Exception
            ' エラーが発生した場合のハンドリング
            ' 非同期処理中のエラーも、ここでキャッチできます
            lblStatus.Text = "エラーが発生しました。"
            MessageBox.Show($"エラー内容: {ex.Message}", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error)
        Finally
            ' 5. 後片付け(必ず実行される)
            ' プログレスバーを通常の状態に戻し、ボタンを再度有効にします
            progressBar1.Style = ProgressBarStyle.Blocks
            btnStart.Enabled = True
        End Try

    End Sub

    ''' <summary>
    ''' 実際の重い処理をシミュレートするメソッド
    ''' </summary>
    Private Sub PerformHeavyTask()
        ' ここが「裏側」で動く処理です。
        ' UIコントロール(LabelやProgressBar)を直接操作してはいけません(エラーになります)。
        
        ' 例:5秒間、何かの計算をしていると仮定
        Dim iterations As Integer = 5
        For i As Integer = 1 To iterations
            ' Thread.Sleep は現在のスレッドを一時停止させます
            ' ここで止まっても、UIスレッドは Task.Run のおかげで止まりません
            Threading.Thread.Sleep(1000) 
        Next
    End Sub

End Class

4. 陥りやすい「3つの罠」と回避策

プロのエンジニアへの道を歩むなら、以下の罠を避ける術を知っておかなければなりません。

罠①:UIコントロールをバックグラウンドから直接触る

`Task.Run` の中(`PerformHeavyTask`内)で、`lblStatus.Text = “処理中…”` のようにラベルを書き換えようとしていませんか?
これは「クロススレッド操作」という致命的なエラーを引き起こします。

  • 対策: 表示の更新は、必ず `Await` を使ってUIスレッドに戻ってから行うか、`Progress(Of T)` クラスを利用しましょう。

罠②:Try…Finally を忘れる

もし重い処理の途中でエラーが起きた場合、`Finally` ブロックがないと、プログレスバーが「Marqueeモード」のまま止まり、ボタンも「無効化」されたままになってしまいます。

  • 対策: UIの状態を元に戻す処理は、必ず `Finally` に記述してください。

罠③:Marqueeを「ずっと」出しっぱなしにする

Marqueeは「今動いていること」を伝えるためのものであり、完了を伝えるものではありません。

  • 対策: 処理が終わったら、必ず `progressBar1.Style = ProgressBarStyle.Blocks`(または `Continuous`)に戻しましょう。

最後に:技術は「思いやり」である

プログラミングにおけるUI設計の本質は、単に見た目を綺麗にすることではありません。
「今、システムの中で何が起きているのか」を、ユーザーに正しく伝え、安心させること。 それは、使う人に対するエンジニアの「思いやり」そのものです。

今回学んだ `Async / Await` と `Marquee` の組み合わせは、現代のWindowsアプリケーション開発における「標準装備」です。これを使いこなせるようになれば、あなたの作るツールは「ただ動くもの」から「信頼される道具」へと進化します。

ここをクリアすれば、Visual Basic (VB.NET) の基本はバッチリですよ。さあ、自信を持って次のステップへ進みましょう!

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