你好我在主窗体的StatusStrip中更新进度条和标签时遇到问题。
StatusStrip中的表单中有2个控件:
基本上我有这种情况:
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(),但它无论如何都不起作用。
提前致谢。
答案 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
中看到消息更改。使用ProgressBar
和ProgressLabel
。
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)
x
和y
是来自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