【发布时间】:2017-02-07 21:27:37
【问题描述】:
为了保持 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
问题为什么在线程中调用ResyncFTP 时MyUI.ChangeLabel 不更新,但在主线程中调用时有效(如下面的代码示例)
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 路线,而是正常的更新路线。我强烈怀疑存在范围问题或洞察力问题。
【问题讨论】:
标签: vb.net multithreading user-interface scope