从后台工作程序中调用的另一个类更新Label和ProgressBar值

时间:2015-07-20 14:26:26

标签: vb.net class background label progress-bar

你好我在主窗体的StatusStrip中更新进度条和标签时遇到问题。

StatusStrip中的表单中有2个控件:

  • 进度条(ToolStripProgressBar)
  • ProgressLabel(ToolStripStatusLabel)

基本上我有这种情况:

Public Class Main
    Public Sub TEST(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles TEST.DoWork
          Dim tmp as New NAMESPACE1.CLASS2(VALUES)
    End Sub 
End Class

Namespace NAMESPACE1
    Public Class CLASS2
         Public Sub New(VALUES)
             Main.Progressbar.Value = 15
             Main.ProgressLabel.Text = "hello!"
         End Sub
     End Class 
End Namespace

问题是控件的文本或值是在代码中更新的(我在断点处看到它),而不是在进度条始终为0%且标签始终为空的情况下更新。

我认为这是主要表单的更新或刷新问题。我试过做Main.Refresh()和Main.Update(),但它无论如何都不起作用。

提前致谢。

2 个答案:

答案 0 :(得分:1)

你有两个问题在起作用。第一个是Main是类名,而不是运行时引用或对象变量。请参阅Idle_Mind使用Me获取运行时对象引用的答案。

第二个问题是,由于在Class2中创建DoWork,因此它在后台线程上创建,这将阻止它访问UI控件(在UI线程上创建)。您将获得非法的跨线程操作异常(即使您没有看到它)。

我建议Class2无法使用ReportProgress方法做任何有用的事情。摆脱它也摆脱了表单引用问题,因为事件是在与UI控件相同的线程上引发的:

Private WithEvents bgw As BackgroundWorker

...
' in a button click or whatever starts the worker:
bgw = New BackgroundWorker
bgw.WorkerReportsProgress = True
bgw.RunWorkerAsync(5)         ' times to loop

...
Private Sub bgw_DoWork(sender As Object, 
           e As DoWorkEventArgs) Handles bgw.DoWork

    ' NOTE
    ' This code executes on a different thread
    '   so do not reference UI controls!

    ' e.Argument is the value passed - amount of work
    Dim max As Integer = CInt(e.Argument)

    For n As Integer = 1 To max
        Threading.Thread.Sleep(250)     ' emulates work
        ' causes the ProgressChanged event to fire:
        bgw.ReportProgress(n, String.Format("{0} of {1}", n.ToString, max.ToString))
    Next

End Sub

Private Sub bgw_ProgressChanged(sender As Object, 
                e As ProgressChangedEventArgs) Handles bgw.ProgressChanged
    'ProgressChanged fires on the UI thread, so it is safe to 
    ' referenece controls here
    TextBox4.Text = e.UserState.ToString
    TextBox4.Refresh()
End Sub

粘贴代码,您可以在TextBox中看到消息更改。使用ProgressBarProgressLabel

也可以
bgw.ReportProgress(n, arg)

第一个参数将映射到e.ProgressPercentage事件中的ProgressChanged。第二个是可选的 - UserState。我用它来传递一个字符串用于说明目的(表单已经知道工作量,因为它告诉BGW要做什么。)

如果Class2有其他目的,只要在UI线程(在表单中)创建并在该线程上使用(即在ProgressChanged事件中),就可以使用它。您还需要一种与控件对话的方法,这样您就不必每次都创建一个新的控件:

Private myObj As Class2           ' declaration
...
myObj = New Class2(Me)             ' instance with frm ref

在第2课:

Public Sub Update(value As Integer, msg As String)
   frmMain.Progressbar.Value = value
   frmMain.ProgressLabel.Text = msg
End Sub

然后在ProgressChanged事件中:

myObj.Update(x, y)

xy是来自whereever的值和消息。

答案 1 :(得分:0)

这是一个按照Plutonix的建议传递对MAIN的引用的示例。我故意保持伪代码样式完整无缺:

Public Class MAIN

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        TEST.RunWorkerAsync()
    End Sub

    Private Sub TEST_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles TEST.DoWork
        Dim tmp As New NAMESPACE1.CLASS2(Me, VALUES) ' <-- Form reference being passed via 1st parameter
    End Sub

End Class

Namespace NAMESPACE1

    Public Class CLASS2

        Private frmMain As MAIN

        Public Sub New(ByVal frmMain As MAIN, VALUES)
            Me.frmMain = frmMain

            Me.frmMain.Progressbar.Value = 15
            Me.frmMain.ProgressLabel.Text = "hello!"
        End Sub

    End Class

End Namespace