为了保持UI的响应能力,我使用一个单独的线程来执行各种过程,例如一些FTP下载。
Private Sub Button11_Click(sender As Object, e As EventArgs) Handles Button11.Click
Dim ThreadResync As System.Threading.Thread
ThreadResync = New System.Threading.Thread(AddressOf Bodacc_ResyncFTP)
ThreadResync.Start()
End Sub
Sub Bodacc_ResyncFTP()
Dim MyBodacc As bodacc_data = New bodacc_data
MyBodacc.Label_Status = Form1.Label1
MyBodacc.ResyncFTP()
End Sub
使用线程更新UI的方法是Delegate
,所以在bodacc_data
我必须
Public Class bodacc_data
......
Delegate Sub UpdateLabelDelg(text As String, ThisLabel As Label)
Public Delegate_label As UpdateLabelDelg = New UpdateLabelDelg(AddressOf set_label)
Public Label_Status = Label
......
Sub set_label(stext As String, ThisLabel As Label)
ThisLabel.Text = stext
End Sub
.....
Sub ResyncFTP()
//says hello
If Label_Status.InvokeRequired = True Then
Label_Status.Invoke(Delegate_label, New Object() {"Working...", Label_Status})
Else
Label_Status.Text = "Working..."
End If
//do stuff
End Sub
End Class
它就像一个魅力。但我有许多类或多或少相同(磁盘更新,数据库更新,FTP更新),并且必须复制/通过所有委托/外部标签声明/迷你子/调用声音愚蠢。
所以我创建了一个类来处理这些UI更新/委托,以便快速访问
Public Class Form_UI
Delegate Sub UpdateLabelDelg(text As String, ThisLabel As Label)
Public Delegate_label As UpdateLabelDelg = New UpdateLabelDelg(AddressOf set_label)
Private Labels(2) As Label
Sub New()
Labels(0) = Form1.Label1
Labels(1) = Form1.Label2
Labels(2) = Form1.Label3
End Sub
Sub set_label(stext As String, ThisLabel As Label)
ThisLabel.Text = stext
End Sub
Public Sub ChangeLabel(ByVal LabelNum As Integer, nText As String)
LabelNum = LabelNum - 1
If Labels(LabelNum).InvokeRequired Then
Labels(LabelNum).Invoke(Delegate_label, New Object() {nText, Labels(LabelNum)})
Else
Labels(LabelNum).Text = nText
Labels(LabelNum).Update()
End If
End Sub
End Class
所以,现在在改版后的bodacc_data
以及所有其他处理类我只有:
Public Class bodacc_data
......
Private MyUI as Form_UI
.....
Sub New()
MyUI = New Form_UI()
End Sub
Sub ResyncFTP()
//says hello
MyUI.ChangeLabel(1, "Working...")
//do stuff
End Sub
End Class
问题为什么MyUI.ChangeLabel
在线程中调用ResyncFTP
时不更新,但如果在主线程中调用则有效(如下面的代码示例中所示)< / p>
Private Sub Button11_Click(sender As Object, e As EventArgs) Handles Button11.Click
Dim MyBodacc As bodacc_data = New bodacc_data
MyBodacc.ResyncFTP()
End Sub
请注意,没有抛出任何错误。值得注意的奇怪之处是<Form_UI>.ChangeLabel()
永远不会进入.Invoke
路由,而是正常的更新路由。我强烈怀疑范围问题或洞察力问题。
答案 0 :(得分:0)
创建Windows窗体应用程序时,您需要设置一个UI线程,该线程应该是所有UI的所有者。 UI线程包含用于更新所有UI的消息泵。
但是你在Button11_Click
中正在做的是创建一个新的线程,然后调用Dim MyBodacc As bodacc_data = New bodacc_data
,然后调用MyUI = New Form_UI()
。
您正在非UI线程上创建表单。没有消息泵,因此UI不会更新。