C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

(追質)時間のかかる処理の進行の表示

[トピック内 23 記事 (1 - 20 表示)]  << 0 | 1 >>

■102556 / inTopicNo.1)  (追質)時間のかかる処理の進行の表示
  
□投稿者/ 焼いも (11回)-(2023/11/17(Fri) 18:27:24)

分類:[VB.NET/VB2005 以降] 

102521に関連しての追加質問で恐縮です。

上が従来ので、下が教えていただいたのを参考にし作ったものです。
どちらも正常に働き結果も同じなのですが、何故か下にした場合には所要時間がとてつもなく掛かってしまうのです。
サンプルではシンプルに作ってますが、実際のは結構複雑な計算もしていて、またその結果データの書き込みもしてもいます。
何故これほどの時間差が出るのか、ご教授のほどお願い致します。

<従来型>
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Using sr As New System.IO.StreamReader("C:\Users\***\***.csv", System.Text.Encoding.GetEncoding("Shift_JIS"))
            Dim dats As Integer = 0   '処理済み数
            ProgressBar1.Minimum = 0 : ProgressBar1.Maximum = 2000 : ProgressBar1.Value = 0
            Label1.Text = "0"
            Do While Not sr.EndOfStream
                Dim dt As String = sr.ReadLine     '1行全てを読み取る

                System.Threading.Thread.Sleep(100)   'ここに全ての計算や結果データの書き込みもあります。

                '処理済み数(ProgressBar1値の更新)
                dats = dats + 1  
                ProgressBar1.Value = dats
                Me.Refresh()
                Label1.Text = dats.ToString()

                If dats = 2000 Then   '一応ここで脱出
                    Exit Do
                End If
            Loop
            sr.Close()
        End Using
    End Sub

<改良型>
    Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Using sr As New System.IO.StreamReader("C:\Users\***\***.csv", System.Text.Encoding.GetEncoding("Shift_JIS"))
            Dim dats As Integer = 0   '処理済み数
            ProgressBar1.Minimum = 0 : ProgressBar1.Maximum = 2000 : ProgressBar1.Value = 0
            Label1.Text = "0"
            Do While Not sr.EndOfStream
                Dim dt As String = sr.ReadLine     '1行全てを読み取る

                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
            sr.Close()
        End Using
    End Sub


引用返信 編集キー/
■102557 / inTopicNo.2)  Re[1]: (追質)時間のかかる処理の進行の表示
□投稿者/ とっちゃん (795回)-(2023/11/17(Fri) 20:50:12)
No102556 (焼いも さん) に返信
> 102521に関連しての追加質問で恐縮です。
> 
> 上が従来ので、下が教えていただいたのを参考にし作ったものです。
> どちらも正常に働き結果も同じなのですが、何故か下にした場合には所要時間がとてつもなく掛かってしまうのです。
> サンプルではシンプルに作ってますが、実際のは結構複雑な計算もしていて、またその結果データの書き込みもしてもいます。
> 何故これほどの時間差が出るのか、ご教授のほどお願い致します。
> 
実際に試したわけでもありませんが、どのくらいの時間差があるのかなどがわかりません。
非同期化しているので、このサンプルのコードの場合であれば
時間がかかるのは、別スレッドで処理している結果、メッセージが処理される分もあると思いますが
毎回 Task をつくって Await するため、作成時間と終了時間と、同期化するための時間、
それと、メッセージ処理がきちんとなされるため(プログレスバーが動いてラベルが変わりますよね?)に
かかる時間とがあるためです。

2000回行っているので、仮に1回あたりの平均が 0.01 秒だったとしても20秒変わってきます。

さて、ではどうするか?というと、Run()をこまめに起こすのではなく、
丸っとひとまとめにして別スレッドで処理する(前回出ていたパターンがこれに該当)か
Dataflowなどを利用してデータ並列(タスク並列)にしていくかのいずれかになります。

処理の具体的な内容がわからないのでどちらが良いかなどは言えませんが一応改めて
今回のサンプルコードをきれいにスレッドアウトしたパターンを提示しておきます。

参考程度にこれだとどの程度変わるか試してみてください。


Private Async Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
    ' 前処理(ProgressBar1, Label1 は自分の所有物なのでほかの人は触れないと思えばいい)
    ProgressBar1.Minimum = 0 : ProgressBar1.Maximum = 2000 : ProgressBar1.Value = 0
    Label1.Text = "0"
    ' Run の中身は丸っと別スレッドで実行される(自分ではない人にお願いしていると思えばよい)
    Await Task.Run(
        Sub()
            Using sr As New System.IO.StreamReader("C:\Users\***\***.csv", System.Text.Encoding.GetEncoding("Shift_JIS"))
                Dim dats As Integer = 0   '処理済み数
                Do While Not sr.EndOfStream
                    Dim dt As String = sr.ReadLine     '1行全てを読み取る

                    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
                ' sr は Using しているので Close を呼ばなくても問題ない
            End Using
        End Sub)
End Sub

引用返信 編集キー/
■102558 / inTopicNo.3)  Re[1]: (追質)時間のかかる処理の進行の表示
□投稿者/ 魔界の仮面弁士 (3710回)-(2023/11/17(Fri) 20:56:06)
2023/11/18(Sat) 11:04:44 編集(投稿者)

# パラメーター指定をミスっていたので修正
# そして 6 分差で被っちゃいました…(手順が違うけれど、ひとまとめに渡すという方針では同じ)

No102556 (焼いも さん) に返信
> Do While Not sr.EndOfStream
>   Dim dt As String = sr.ReadLine '1行全てを読み取る
>   Await Task.Run(

依頼者「No1 を処理してください」
作業者「了解…(長い処理)…終わりました」
依頼者「(ProgressBar を +1)」
依頼者「No2 を処理してください」
作業者「了解…(長い処理)…終わりました」
依頼者「(ProgressBar を +1)」


これじゃ遅いですよ。
細切れにして何度も依頼しなおさないで、
全部まとめて、1 回だけ依頼しましょう。


依頼者「これらのデータを順に処理して、終わったものから随時報告してください」


進捗通知のための IProgress(Of T) を使ってみた例。


Sub 画面表示更新処理(hoge As 任意の型)
 'ここは呼び出し元のスレッドで動くので、ProgressBar 等を操作しても構わない
 '引数 hoge から進捗状況を受け取り、Label や ProgressBar 等に反映
End Sub

'今回の本題は IProgress
'それ以外の引数は不要なら省いてもよいし、別の引数を追加してもよい
Function 時間のかかる処理本体部(argument As 処理させたいデータ, p As IProgress(Of 任意の型), cancelToken As CancellationToken) As Boolean
 'ここはワーカースレッドで動くので、画面操作は禁止
 For Each foo In argument
  If cancelToken.IsCancellationRequested Then 'キャンセル依頼あり
   Debug.WriteLine("キャンセル処理のための処理")
   Return False '中断
  End If

  Debug.WriteLine("長い処理")
  Thread.Sleep(1000)

  '引数 p を通じて進捗状況を記録
  p.Report( 進捗状況データ )

 Next
 Return True '全件処理完了
End Function

Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
 Button1.Enabled = False '多重呼び出しされないようにブロック

 '進捗報告のための IProgress(Of T) 実装を用意
 Dim p As New Progress(Of 任意の型)(AddressOf 画面表示更新処理)

 '中断依頼を受け付けるためのトークンを用意(今回は使ってない)
 Me.cancelTokensource = New CancellationTokenSource()
 Dim cToken = Me.cancelTokenSource.Token

 '時間のかかる処理
 Dim completed = Await Task.Run(Function() 時間のかかる処理本体部(作業依頼データ, p, cToken))
 If completed Then
  Label1.Text = "完了"
 Else
  Label1.Text = "中断"
 End If

 Button1.Enabled = True
End Sub
Private cancelTokenSource As CancellationTokenSource
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
 '中断依頼
 cancelTokenSource?.Cancel()
End Sub



なお、順次処理である必要が無い場合は Parallel.For や Parallel.ForEach などを使う手法もあります。
(データを幾つかに分割し、複数の作業者に同時に依頼して並列処理させるイメージ)
引用返信 編集キー/
■102559 / inTopicNo.4)  Re[2]: (追質)時間のかかる処理の進行の表示
□投稿者/ 焼いも (12回)-(2023/11/18(Sat) 10:24:52)
No102557 (とっちゃん さん) に返信

> 2000回行っているので、仮に1回あたりの平均が 0.01 秒だったとしても20秒変わってきます。
そのようなことなんでしょうね。
残念なことには効果のほどは見られませんでした。

引用返信 編集キー/
■102560 / inTopicNo.5)  Re[2]: (追質)時間のかかる処理の進行の表示
□投稿者/ 焼いも (13回)-(2023/11/18(Sat) 10:40:26)
No102558 (魔界の仮面弁士 さん) に返信

申し訳ございません。
こちらのレベルが低過ぎて理解不能でした。

それと最初の質問にもありますように、
FunctionやSubは有っても良いのですが、原型は出来るだけ崩さずにお願いをしたいとこもあります。
即ち、時間のかかる処理はButton1内でお願いもしたいのです。


引用返信 編集キー/
■102561 / inTopicNo.6)  Re[3]: (追質)時間のかかる処理の進行の表示
□投稿者/ WebSurfer (2802回)-(2023/11/18(Sat) 12:05:31)
No102560 (焼いも さん) に返信

このスレッドでも基本的に前のスレッドと同じことをしているのですよね。

先のスレッドでは解決したと言っていて、「解決済み」マークも自分で付けましたよね。
解決したのではないのですか?
引用返信 編集キー/
■102562 / inTopicNo.7)  Re[2]: (追質)時間のかかる処理の進行の表示
□投稿者/ WebSurfer (2803回)-(2023/11/18(Sat) 15:04:31)
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

引用返信 編集キー/
■102563 / inTopicNo.8)  Re[4]: (追質)時間のかかる処理の進行の表示
□投稿者/ 焼いも (14回)-(2023/11/18(Sat) 15:29:10)
No102561 (WebSurfer さん) に返信

> 解決したのではないのですか?

申し訳ございません。
関連しての新たな使用法にての質問をさせていただいています。

引用返信 編集キー/
■102564 / inTopicNo.9)  Re[5]: (追質)時間のかかる処理の進行の表示
□投稿者/ WebSurfer (2804回)-(2023/11/18(Sat) 15:52:38)
No102563 (焼いも さん) に返信

> 関連しての新たな使用法にての質問をさせていただいています。

結局は、前のスレッドの質問と同じく、WinForms アプリの UI スレッドをブロックしないよう
に、複数の

System.Threading.Thread.Sleep(100)

を UI スレッドとは別のスレッドで非同期に実行するということで、何も「新た」なことはあり
ません。

引用返信 編集キー/
■102567 / inTopicNo.10)  Re[6]: (追質)時間のかかる処理の進行の表示
□投稿者/ 焼いも (15回)-(2023/11/18(Sat) 20:07:14)
No102564 (WebSurfer さん) に返信

ふつつかな点お詫び致します。
前回の質問でも具体的に教えてもいただき、ようやくにして宿願の一端をも解決が出来
本当に有難くただただ感謝の限りでございます。

引用返信 編集キー/
■102572 / inTopicNo.11)  Re[2]: (追質)時間のかかる処理の進行の表示
□投稿者/ とっちゃん (796回)-(2023/11/19(Sun) 02:11:01)
No102567 (焼いも さん) に返信

最近この手のことは誰も書かないので、少し脱線気味な話になりますが
おそらく根本的であろう部分についてのお話を参考程度に。

.NET(Framework も Core も同様)に限らず、Windows のGUIアプリは画面表示に
関わる処理は、原則 UIスレッド上で行う必要があります。

また、アプリが応答なしにならないようにするには、UIスレッドが常に反応できる状態に
しておく必要があります。

UIスレッドって何?というのはあると思いますが、とりあえず今は
「GUIアプリのUIスレッドは、メインスレッドのこと」と覚えておけばいいでしょう。

UIスレッド自体はメインスレッド以外でもなり得るのですが、多くの場合メインスレッド以外で
UIスレッドを作ることも使うこともないので。

今回解決するべき部分は、UIスレッドが常に反応できる状態というのがどういうことか?というところになります。
言い方を変えると、レスポンスが良い(反応がよい)アプリを作るための基礎の部分でです。


ちょっと古い記事ですが、ざっくりとしているものの重要な点は
一通り網羅してるのでこの辺りの記事を一度読んでおくと良いと思います。

https://atmarkit.itmedia.co.jp/fdotnet/chushin/masterasync_01/masterasync_01_01.html


そのうえで、こちらの「高度な .NET プログラミングのドキュメント」から
「非同期プログラミング(主にTAP)」と、「並列プログラミング」を学習していくとよいでしょう。

https://learn.microsoft.com/ja-jp/dotnet/navigate/advanced-programming/?WT.mc_id=DT-MVP-32182

「高度な」とあるように、どちらの内容も基本的な部分が出来ていないとわからないところが多いと思います。

なお、どちらもマルチスレッドプログラミングですが
「非同期プログラミング」は、主にUIスレッドの応答性を高めるための技術(レスポンスの向上)
「並列プログラミング」は、高速化のための技術(パフォーマンスの向上)になります。

引用返信 編集キー/
■102574 / inTopicNo.12)  Re[7]: (追質)時間のかかる処理の進行の表示
□投稿者/ WebSurfer (2806回)-(2023/11/19(Sun) 10:22:59)
No102567 (焼いも さん) に返信

> ふつつかな点お詫び致します。
> 前回の質問でも具体的に教えてもいただき、ようやくにして宿願の一端をも解決が出来
> 本当に有難くただただ感謝の限りでございます。

質問者さんにお願いしたいのは、お詫びとかお礼を言ってもらうことではなくて、
私の回答・レスに対してきちんとフィードバックを返してもらうことです。

具体的には、No102562 をよく読んで、貼ってあるコードを試して、私が検証した
結果「ほとんど差はない」を質問者さんも自分の環境で検証・確認してもらい、
その結果を書いてもらうことです。

そのようにしてもらえないと話が進みません。
引用返信 編集キー/
■102578 / inTopicNo.13)  Re[8]: (追質)時間のかかる処理の進行の表示
□投稿者/ 焼いも (16回)-(2023/11/20(Mon) 00:00:09)
No102574 (WebSurfer さん) に返信

> 具体的には、No102562 をよく読んで、貼ってあるコードを試して、私が検証した
> 結果「ほとんど差はない」を質問者さんも自分の環境で検証・確認してもらい、
> その結果を書いてもらうことです。
>
> そのようにしてもらえないと話が進みません。

No102562は当方宛てでは無かった為、途中で呼び飛ばしてしまい気付かずに申し訳ありません。

> Button1 が遅いのは Me.Refresh() のせいです。
やはりそうだったのですね。
欲を出して付けたのですが以降はLabel表示は無しにとします。

その上で、貴サンプルのButton4を、
当方の実際のプログラムに実装し試したところ処理時間は約60秒となり、
それに対して従来からのでは約25秒となり、
即ち一番早いButton4を以てしても約2.4倍遅い結果ともなってしまいました。

ちなみにこのテストは実際のよりもデータ数を減らしてのものです。




引用返信 編集キー/
■102579 / inTopicNo.14)  Re[3]: (追質)時間のかかる処理の進行の表示
□投稿者/ 焼いも (17回)-(2023/11/20(Mon) 00:07:17)
No102572 (とっちゃん さん) に返信

> 最近この手のことは誰も書かないので、少し脱線気味な話になりますが
> おそらく根本的であろう部分についてのお話を参考程度に。

申し訳ないですが、その参考程度にしても今のところでは頭がついていかず
まだまだどうやら時間が掛りそうです。




引用返信 編集キー/
■102581 / inTopicNo.15)  Re[4]: (追質)時間のかかる処理の進行の表示
□投稿者/ とっちゃん (797回)-(2023/11/20(Mon) 01:48:22)
No102579 (焼いも さん) に返信
> ■No102572 (とっちゃん さん) に返信
>
>>最近この手のことは誰も書かないので、少し脱線気味な話になりますが
>>おそらく根本的であろう部分についてのお話を参考程度に。
>
> 申し訳ないですが、その参考程度にしても今のところでは頭がついていかず
> まだまだどうやら時間が掛りそうです。
>
高度なプログラミングと書いてあるように、要求される技術レベルも相応のものです。
なので学習にはそれなりに時間がかかると思いますので頑張ってください。
引用返信 編集キー/
■102582 / inTopicNo.16)  Re[9]: (追質)時間のかかる処理の進行の表示
□投稿者/ WebSurfer (2807回)-(2023/11/20(Mon) 09:06:05)
No102578 (焼いも さん) に返信

>>具体的には、No102562 をよく読んで、貼ってあるコードを試して、私が検証した
>>結果「ほとんど差はない」を質問者さんも自分の環境で検証・確認してもらい、
>>その結果を書いてもらうことです。
>>
>>そのようにしてもらえないと話が進みません。
>
> No102562は当方宛てでは無かった為、途中で呼び飛ばしてしまい気付かずに申し訳ありません。

話は通じてますか? 「結果を書いてもらうことです」とお願いしましたが、どうなりました?

>>Button1 が遅いのは Me.Refresh() のせいです。
> やはりそうだったのですね。
> 欲を出して付けたのですが以降はLabel表示は無しにとします。

このスレッドであなたが問題にしているのは「従来型」より「改良型」が大幅に遅いということですよね。

それと関係ないでしょう。

> その上で、貴サンプルのButton4を、
> 当方の実際のプログラムに実装し試したところ処理時間は約60秒となり、
> それに対して従来からのでは約25秒となり、
> 即ち一番早いButton4を以てしても約2.4倍遅い結果ともなってしまいました。

「当方の実際のプログラム」って何だか分かりませんが、私のサンプルとは違うことをしているのですよね。

しかも、どういう理屈で私のサンプルが button 1〜3 と比べて早くなるのか分かってやってないのでは?

違うことを、早くなる理屈とは違うように実装した結果、違う結果になるのは当たり前です。
引用返信 編集キー/
■102583 / inTopicNo.17)  Re[10]: (追質)時間のかかる処理の進行の表示
□投稿者/ 焼いも (18回)-(2023/11/20(Mon) 15:45:34)
No102582 (WebSurfer さん) に返信

> 話は通じてますか? 「結果を書いてもらうことです」とお願いしましたが、どうなりました?
No102578に書いた積りですがそれでは駄目なのでしょう、きっと。。

> 「当方の実際のプログラム」って何だか分かりませんが、私のサンプルとは違うことをしているのですよね。
違うことともなりますが、目的が「当方の実際のプログラム」に当てはめ使うことにあるからです。

> しかも、どういう理屈で私のサンプルが button 1〜3 と比べて早くなるのか分かってやってないのでは?
何故、button 1〜3に比べbutton 4が早いかも分かっていませんし、例え説明をいただいても趣味で楽しんでる者には理解は出来ないと思います。

> 違うことを、早くなる理屈とは違うように実装した結果、違う結果になるのは当たり前です。
確かにそうかもしれませんが、Button4を「当方の実際のプログラム」に実装した時のみ何故遅くなるかが不思議でなりません。
ちなみにここでの System.Threading.Thread.Sleep(100) の部分でしてるのは、簡単な計算と分類、その結果のファイルへの書き込みで、そのことは今回の質問にも書いた通りです。

あと、唯一遅くなる可能性があるとすれば、ひとつのForm内に複数のこれのよく似た使い方をしているくらいですが、それらとて使われた痕跡はありません。

また不可解な説明もしてるのでしょうね。
今、分かってるのはこの程度です。


引用返信 編集キー/
■102584 / inTopicNo.18)  Re[5]: (追質)時間のかかる処理の進行の表示
□投稿者/ 焼いも (19回)-(2023/11/20(Mon) 15:47:57)
No102581 (とっちゃん さん) に返信

> 高度なプログラミングと書いてあるように、要求される技術レベルも相応のものです。
> なので学習にはそれなりに時間がかかると思いますので頑張ってください。
ありがとうございます。
趣味として楽しんでる者にはかなりのハードルが高いですが。

引用返信 編集キー/
■102585 / inTopicNo.19)  Re[11]: (追質)時間のかかる処理の進行の表示
□投稿者/ WebSurfer (2808回)-(2023/11/20(Mon) 17:13:41)
No102583 (焼いも さん) に返信

もう一回だけ説明します。これで話が通じなければ時間と労力の無駄なので自分は撤退します。

> No102578に書いた積りですがそれでは駄目なのでしょう、きっと。。

ダメです。有用な情報が何もありません。

> No102562 をよく読んで、貼ってあるコードを試して、私が検証した
> 結果「ほとんど差はない」を質問者さんも自分の環境で検証・確認してもらい、
> その結果を書いてもらうことです。

・・・というのをもう少し具体的に書きます。

No102562 の私のサンプルコードの Button1_Click と Button2_Click を、「当方の実際のプログ
ラム」とか余計なものは一切入れずに、そのままコピペして、質問者さんの環境で動かして計測
結果を書いてください。

最初の質問にあった<従来型>と<改良型>に該当するのが、それぞれ Button1_Click と Button2_Click
です。

質問者さんの環境で試して、同じ結果(実行時間のほとんど差はない)ということが確認できれば、
遅くなる原因が少しは絞れてきて(少なくともマルチスレッドにしたことが遅くなった原因ではな
さそうと推測できて)、問題解決に向けて話を進めることができそうということです。


引用返信 編集キー/
■102586 / inTopicNo.20)  Re[6]: (追質)時間のかかる処理の進行の表示
 
□投稿者/ とっちゃん (798回)-(2023/11/20(Mon) 17:37:23)
No102584 (焼いも さん) に返信
> ■No102581 (とっちゃん さん) に返信
>
>>高度なプログラミングと書いてあるように、要求される技術レベルも相応のものです。
>>なので学習にはそれなりに時間がかかると思いますので頑張ってください。
> ありがとうございます。
> 趣味として楽しんでる者にはかなりのハードルが高いですが。
>
趣味として楽しむ範疇は人それぞれなので、ハードルが高いなら超えなくてもいいと思います。

その方向で行くのであれば、無理してマルチスレッドにするのではなく
当初の目的にある、応答なしにならないという処理だけ素直に挟み込めばいいでしょう。
具体的には以下のような感じ。

具体的には、最初のButton1の処理の以下の部分を

ProgressBar1.Value = dats
Me.Refresh()
Label1.Text = dats.ToString()

以下のように変更してみてください(Me.Refreshはあえてコメントで残してある)

ProgressBar1.Value = dats
' Me.Refresh()
Label1.Text = dats.ToString()
Application.DoEvents()

強制再描画ではなく、たまったイベントを処理することでアプリケーションが応答なしに
ならない状態になります。

ただし実行速度が向上するわけではないので、処理時間が短くなることはありません。

これも応答なしにならないためのプログラムとしては、正解の一つといえます。

引用返信 編集キー/

このトピックをツリーで一括表示

次の20件>
トピック内ページ移動 / << 0 | 1 >>

管理者用

- Child Tree -