|
■No102557 (とっちゃん さん) に返信
> 非同期化しているので、このサンプルのコードの場合であれば
> 時間がかかるのは、別スレッドで処理している結果、メッセージが処理される分もあると思いますが
> 毎回 Task をつくって Await するため、作成時間と終了時間と、同期化するための時間、
> それと、メッセージ処理がきちんとなされるため(プログレスバーが動いてラベルが変わりますよね?)に
> かかる時間とがあるためです。
自分もそうだろうなぁと思ったのですが、念のため試してみるとほとんど差はないという
結果になりました。
検証に使ったのは以下のコードです。元のコードにあった CSV ファイルを読むという余計
な操作は削除しましたが、それ以外は質問 No102556 と、とっちゃんさんのレス No102557
とほぼ同じで、それに時間を測るための StopWtach を追加しています。
最後の、Button4_Click のコードは、私が先のスレッドで書いたレス No102531 に書いた
ように、2000 個 Task.Run でキューに配置して、全部の終了を await Task.WhenAll(...)
で待機するものです。
結果は:
Button1: 3' 40"
Button2: 3' 36"
Button3: 3' 36"
Button4: 0' 18" (2 回目以降は 8" 前後)
となりました。Button1 が遅いのは Me.Refresh() のせいです。
ひょっとしたら何か自分の勘違い・間違いとかがあるかもしれませんので、閲覧者の方に
確認していただけると幸いです。
自分の環境は Windows 10 Pro 22H2, VS2022 v17.8.0, .NET Framework 4.8 です。
Public Class Form5
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim dats As Integer = 0 '処理済み数
ProgressBar1.Minimum = 0 : ProgressBar1.Maximum = 2000 : ProgressBar1.Value = 0
Label1.Text = "0"
Label2.Text = ""
Dim stopWatch As New Stopwatch()
stopWatch.Start()
Do While True
System.Threading.Thread.Sleep(100) 'ここに全ての計算や結果データの書き込みもあります。
'処理済み数(ProgressBar1値の更新)
dats = dats + 1
ProgressBar1.Value = dats
Me.Refresh()
Label1.Text = dats.ToString()
'Application.DoEvents()
If dats = 2000 Then '一応ここで脱出
Exit Do
End If
Loop
stopWatch.Stop()
Dim ts As TimeSpan = stopWatch.Elapsed
Dim elapsedTime As String = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10)
Label2.Text = elapsedTime
End Sub
Private Async Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim dats As Integer = 0 '処理済み数
ProgressBar1.Minimum = 0 : ProgressBar1.Maximum = 2000 : ProgressBar1.Value = 0
Label1.Text = "0"
Label2.Text = ""
Dim stopWatch As New Stopwatch()
stopWatch.Start()
Do While True
Await Task.Run(
Sub()
System.Threading.Thread.Sleep(100) 'ここに全ての計算や結果データの書き込みもあります。
End Sub)
'処理済み数(ProgressBar1値の更新)
dats = dats + 1
ProgressBar1.Value = dats
Label1.Text = dats.ToString()
If dats = 2000 Then '一応ここで脱出
Exit Do
End If
Loop
stopWatch.Stop()
Dim ts As TimeSpan = stopWatch.Elapsed
Dim elapsedTime As String = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10)
Label2.Text = elapsedTime
End Sub
Private Async Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
ProgressBar1.Minimum = 0 : ProgressBar1.Maximum = 2000 : ProgressBar1.Value = 0
Label1.Text = "0"
Label2.Text = ""
Dim stopWatch As New Stopwatch()
stopWatch.Start()
Await Task.Run(
Sub()
Dim dats As Integer = 0
Do While True
System.Threading.Thread.Sleep(100) 'ここに全ての計算や結果データの書き込みもあります。
dats = dats + 1
Invoke(
Sub()
' 別のスレッドからは自分の所有物にアクセスできないので自分
' でやるために Invoke(自分の処理として呼び出し)してもらう
ProgressBar1.Value = dats
Label1.Text = dats.ToString()
End Sub)
If dats = 2000 Then '一応ここで脱出
Exit Do
End If
Loop
End Sub)
Stopwatch.Stop()
Dim ts As TimeSpan = Stopwatch.Elapsed
Dim elapsedTime As String = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10)
Label2.Text = elapsedTime
End Sub
Private Async Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Dim dats As Integer = 0 '処理済み数
Label1.Text = ""
Label2.Text = ""
Dim stopWatch As New Stopwatch()
stopWatch.Start()
Dim taskList = New List(Of Task)()
Do While True
taskList.Add(Task.Run(
Sub()
System.Threading.Thread.Sleep(100) 'ここに全ての計算や結果データの書き込みもあります。
End Sub))
dats = dats + 1
If dats = 2000 Then '一応ここで脱出
Exit Do
End If
Loop
Await Task.WhenAll(taskList)
stopWatch.Stop()
Dim ts As TimeSpan = stopWatch.Elapsed
Dim elapsedTime As String = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10)
Label2.Text = elapsedTime
End Sub
End Class
|