コードを書くのを躊躇して仕舞います。
少し、面倒なのでしたね。
自分としては、余り、出番が無いので、備忘録的に。 ;)
先ずは、お断りして置きます。
これから書く事は、素人の 悪足掻き! です。
レベルは低いので、そのお心算で、ご覧下さい。
ProgressBar 。
進捗状況を明示する コントロール ですね。
私、余り、使いません ... 。
だって、コードを書くのが簡単では無いから ... 。 X|
通常、Wait Cursor で お茶を濁しています。
今は作業実行中ですよ! と、ね。
でも、今回、WPF & .mdf (LocalDB) を使ったもので、
待っていて不安になるケースがありました。
データ自動取得で、ファイル群 や DB を操作するのですが、
ただ、カーソルがくるくる回っているのを眺めていて、不安が過ったのです。
一体、どれくらいの時間が掛かるのか ... ?。
事後に、
それは、LocalDB が Stopped していて、再度 Session を開くのに、
大半の時間を費やしていたのだろうと、分かったのですが、
最初は、
対象ファイルを全て舐めて行く必要がある為に、
単に、数多のファイルを相手に、奮闘しているのだろうと、想像し、
進捗状況を提示する必要があると感じたのです。
進捗状況 なら ProgressBar の出番!です。
でも、これって、割と面倒なコードが必要です。
UI 処理 と 実処理 とを 分けないといけないからですね。
以下に、稚拙なコードを載せます。
実際には、DB と DataGrid なのですが、
オマケに、DB 上の有無確認と タグ取得と が必要なので 結構 複雑なのですが、
端折って、ListBox と Sleep で代用(単純化)します。
ListBox と Button とを画面左右に各1個配置し、右のみ ProgressBar も配置します。
左は普通に ListBox Items を加えるロジック、
これに対し、右は、
そのコードから ProgressBar に進捗を表示するロジックに変えたケースです。
Async を使った Button Click Handler と、
それを受ける Await Task.Run(Function() DoWork()) の DoWork Routine(Function) と
進捗状況を渡す ShowProgress の Routine(Sub) と、
から構成されますね。
良く例示されるコードは 中断 を含むものですが、
今回は DB 登録ですから、中断はさせません。 (可能ですが、余り、意味が無い ... ?)
ですから、 ProgressBar のサンプルとしてはシンプルだと思います。
先ずは、こんなコード(画面左用)からスタートしたとします。
Private Sub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click
Dim files As New List(Of String)
For i As Integer = 1 To 20
files.Add((11111 * i).ToString & ".wma")
Next
Mouse.OverrideCursor = Cursors.Wait
For Each item In files
'Handling File's Metadata
'
Me.ListBox1.Items.Add(item)
' Sleeping As Hard Works
Threading.Thread.Sleep(500)
Next
Mouse.OverrideCursor = Nothing
MessageBox.Show("End Of Work > " & files.Count.ToString & " Files",
Me.Title)
End Sub
このコードから ProgressBar を活かす画面右用を。
Class MainWindow
Private files2 As New List(Of String)
' 中略 (Omission : Private Sub Button1_Click)
Private Async Sub Button2_Click(sender As Object, e As RoutedEventArgs) Handles Button2.Click
'Private Sub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click
Dim files As New List(Of String)
For i As Integer = 1 To 20
files.Add((11111 * i).ToString & ".wma")
Next
Mouse.OverrideCursor = Cursors.Wait
' このブロックを外に出す (Take This Block Out As 'DoWork')
'For Each item In files
' Me.ListBox1.Items.Add(item)
' ' Sleeping As Hard Works
' Threading.Thread.Sleep(500)
'Next
' このブロックを外に出す (Take This Block Out ; End)
' ProgressBar Start
Me.ProgressBar2.Minimum = 0.0 'ProgressBar
Me.ProgressBar2.Maximum = 100.0 'ProgressBar
Dim p1 = New Progress(Of Integer)(AddressOf ShowProgress)
Dim result1 As String = Await Task.Run(Function() DoWork(p1, files)) 'DoWork
For Each item2 In files2
Me.ListBox2.Items.Add(item2)
Next
' ProgressBar End
Mouse.OverrideCursor = Nothing
MessageBox.Show("End Of Work > " & files.Count.ToString & " Files",
Me.Title)
'End Sub
End Sub
Private Sub ShowProgress(percent As Double)
Me.ProgressBar2.Value = percent
End Sub
Private Function DoWork(progress As IProgress(Of Integer), ByRef files As List(Of String))
Dim i As Integer = 1
For Each item In files
'Handling File's Metadata
'
'Me.ListBox1.Items.Add(item) ' Never Touch UI Element!!! > files2 As New Field Variable
files2.Add(item)
' Sleeping As Hard Works
Threading.Thread.Sleep(500)
'Report Progress
progress.Report(i / files.Count * 100.0)
i += 1
Next
Return "Done"
End Function
End Class
これを実行すると、右の方が遅い気がしますね。 下図参照 Debug Mode 。
ProgressBar の表示をする分、負荷が掛かっているのでしょうが、
見ていれば、多少遅くても、進捗状況を把握出来るので、安心感はあるのではないでしょうか?。
それにしても、 ProgressBar は ... 難しい ... 。
0 件のコメント:
コメントを投稿