运行按钮单击事件时窗体不会更新

时间:2013-11-14 13:57:32

标签: vb.net multithreading forms progress-bar refresh

我正在尝试更新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 

所以基本上当你运行它时,它会很好地执行和更新进度条,但标签不会更新。我认为它可能与多线程有关,而且表单不会得到不断的更新。

3 个答案:

答案 0 :(得分: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()控件。您调用其ReportProgress()方法来触发ProgressChanged()事件。从该事件可以安全地更新UI。当后台线程中的工作完成后,您将获得RunWorkerCompleted()事件。请注意,如果要使用progress事件,则必须将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

答案 1 :(得分:0)

如果您认为标签的值正在更改,但屏幕未更新,您是否尝试过刷新方法?

例如:

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

答案 2 :(得分:0)

我相信其他人可以解释为什么会这样,但我总是不得不使用以下内容来更新标签,否则不会:

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