1

Visual Basic で各メソッドの最後に進行状況バーを更新しようとしていますが、問題は、label1.Text が各メソッドの開始時に更新されず、更新されることです。

Public Class Form2

    Private Const METHOD_COUNT = 4

    Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ProgressBar1.Maximum = METHOD_COUNT
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Method_One()
        Method_Two()
        Method_Three()
        Method_Four()
    End Sub

    Private Sub Method_One()
        Label1.Text = "Loading Method One"
        ProgressBar1.Value += 1
        'Threading.Thread.Sleep(1000)
    End Sub

    Private Sub Method_Two()
        Label1.Text = "Loading Method Two"
        ProgressBar1.Value += 1
        'Threading.Thread.Sleep(1000)
    End Sub

    Private Sub Method_Three()
        Label1.Text = "Loading Method Three"
        ProgressBar1.Value += 1
        'Threading.Thread.Sleep(1000)
    End Sub

    Private Sub Method_Four()
        Label1.Text = "Loading Method Four"
        ProgressBar1.Value += 1
        'Threading.Thread.Sleep(1000)
    End Sub
End Class 

したがって、基本的にこれを実行すると、進行状況バーが適切に実行および更新されますが、ラベルは更新されません。マルチスレッドと関係があり、フォームが常に更新されないという事実があると思います。

4

3 に答える 3

2

「クイックフィックス」は、へのApplication.DoEvents()各呼び出しの前に追加することSleep()です:

Public Class Form2

    Private Const METHOD_COUNT = 4

    Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ProgressBar1.Maximum = METHOD_COUNT
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Method_One()
        Method_Two()
        Method_Three()
        Method_Four()
    End Sub

    Private Sub Method_One()
        Label1.Text = "Loading Method One"
        ProgressBar1.Value += 1
        Application.DoEvents()
        Threading.Thread.Sleep(1000)
    End Sub

    Private Sub Method_Two()
        Label1.Text = "Loading Method Two"
        ProgressBar1.Value += 1
        Application.DoEvents()
        Threading.Thread.Sleep(1000)
    End Sub

    Private Sub Method_Three()
        Label1.Text = "Loading Method Three"
        ProgressBar1.Value += 1
        Application.DoEvents()
        Threading.Thread.Sleep(1000)
    End Sub

    Private Sub Method_Four()
        Label1.Text = "Loading Method Four"
        ProgressBar1.Value += 1
        Application.DoEvents()
        Threading.Thread.Sleep(1000)
    End Sub

End Class

正しい修正」は、「作業」をメインの UI スレッドで行うべきではないことです。これは、ボタン クリック ハンドラーからこれらのメソッドを呼び出すことです。代わりに、UI がそれ自体を更新できるように、作業をバックグラウンド スレッドに移動する必要があります。BackgroundWorker()コントロールの使用を見てみましょう。ProgressChanged() イベントを発生させる ReportProgress() メソッドを呼び出します。そのイベントから、UI を安全に更新できます。バックグラウンド スレッドでの作業が完了すると、RunWorkerCompleted() イベントが発生します。進行状況イベントを使用する場合は、WorkerReportsProgress() プロパティを True に設定する必要があることに注意してください。

Public Class Form2

    Private Const METHOD_COUNT = 4

    Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ProgressBar1.Maximum = METHOD_COUNT
        BackgroundWorker1.WorkerReportsProgress = True
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Not BackgroundWorker1.IsBusy Then
            Button1.Enabled = False
            BackgroundWorker1.RunWorkerAsync()
        End If
    End Sub

    Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Method_One()
        Method_Two()
        Method_Three()
        Method_Four()
    End Sub

    Private Sub Method_One()
        BackgroundWorker1.ReportProgress(1, "Loading Method One")
        Threading.Thread.Sleep(1000)
    End Sub

    Private Sub Method_Two()
        BackgroundWorker1.ReportProgress(2, "Loading Method Two")
        Threading.Thread.Sleep(1000)
    End Sub

    Private Sub Method_Three()
        BackgroundWorker1.ReportProgress(3, "Loading Method Three")
        Threading.Thread.Sleep(1000)
    End Sub

    Private Sub Method_Four()
        BackgroundWorker1.ReportProgress(4, "Loading Method Four")
        Threading.Thread.Sleep(1000)
    End Sub

    Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
        Label1.Text = e.UserState
        ProgressBar1.Value = e.ProgressPercentage
    End Sub

    Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        Button1.Enabled = True
        MessageBox.Show("Done!")
    End Sub

End Class
于 2013-11-14T15:41:31.347 に答える
0

他の誰かがこれがなぜなのかを説明できると確信していますが、そうでなければラベルを更新しない場合は、常に次を使用してラベルを更新する必要がありました。

Private Sub Method_Three()
    With Label1
        .Text = "Loading Method Three"
        .Refresh
    End With
    ProgressBar1.Value += 1
    'Threading.Thread.Sleep(1000)
End Sub
于 2013-11-14T15:01:21.987 に答える