VisualBasic(脳トレ的アプリ006: ProgressBarのずれ)

■問題を回答する時間について検討してみる。
前回までで問題作成部分についてはできた。今回は、問題を回答する時間について考えてみる。

前回挙げた動画の通り、今のコードは1秒ごとにProgressBarを進め、10秒に達したら終了する形になっている。コードは、TimerとProgressBarを使った下のような感じ。

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        ProgressBar1.PerformStep()

        If ProgressBar1.Value = ProgressBar1.Maximum Then
            Dispose()
        End If

    End Sub

Timer1_Tickは、指定した間隔(Interval)ごとに中のコードを実行。ProgressBar1.PerformStep()は、指定したStepだけバーを進める。ProgressBarやTimerは、Visual Studioから追加したりプロパティ変更したりできる(下の図は、Timer1のInterval = 1000ミリ秒)。ProgressBarは、Step = 10, Maximum = 100としている。
そのため、上のコードは1秒ごとに10だけバーを進め、100になった時点で終了となる。


バーが100になった時点ですぐ終了するが、ProgressBar1.PerformStep()で数値が更新されるタイミングと画面上でバーが進むタイミングに少しラグがあるらしく、見た目上、バーが最後まで行く前に終了してしまう。

Timerの設定を1000ミリ秒から10ミリ秒ごとにし、ProgressBarのStep, Maximumをそれぞれ1, 1000にすれば、同じ10秒でも、上では10回のコードの実行に対して1000回の実行となる。バーの進み方が滑らかになるけど、最後まで行く前に終了するのは変わらない。

終了前に少し待つコードなど入れればいいのかな?と思い、Thread.Sleepを入れてみる。

 Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        ProgressBar1.PerformStep()

        If ProgressBar1.Value = ProgressBar1.Maximum Then

            System.Threading.Thread.Sleep(1000)
            Dispose()
        End If
    End Sub

しかし、これで停止させると、バーを進める部分も停止してしまうよう。

次に、Task.Delayでの停止を考えてみた。下のようにAsync, Awaitで処理すると、バーを進める部分の停止はせず、待つことができた。ただ、終わりの判定は、バーが最後まで行く前にされてしまう。
数値が最後まで行ったとき(ProgressBar1.Value = ProgressBar1.Maximum)をデバックで見てみると、 やはりバー自体は最後まで行っていない(下の図)。

   Private Async Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        ProgressBar1.PerformStep()

        If ProgressBar1.Value = ProgressBar1.Maximum Then
            Await Task.Delay(600)
        End If

        If ProgressBar1.Value = ProgressBar1.Maximum Then
            Dispose()
        End If

    End Sub

いろいろと触ってみると、上のデバッグ時の状態でも、回答すれば次の問題に行きバーをリセットできた。

Timer, ProgressBarの設定とTask.Delayの値を調整して、見た感じバーが最後まで行ったら終了になるようにする。設定は、Timer interval = 1ミリ秒、ProgressBar Step = 1, Maximum = 200、Task.Delay(600)とした。何度か動かしてみて、10秒では長すぎるので、だいたい3,4秒くらいで終了になるようにした。

ProgressBarのずれについては、ネットでも似たような問題があるよう。何か定番の解決方法があるかもしれないけど、今回はここまで。