|  | ■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
 |