我是一名学生,试图自己学习VB.NET。今天我想解决BackgroundWorker组件。我在网上找到了一篇很好的文章:How To Use a Background Worker。我成功地完成了演练,甚至执行了“冒险”部分,该部分涉及使用委托使用控件更新线程。
现在我找到了一个我不明白它是如何工作的部分。总结以下代码,我有一个委托,其签名中有一个Label和一个String。然后我有一个在工作线程上调用的子例程。在这个子例程中,创建了委托,并且(我猜)再次运行,以便它在同一个(主)线程上。如果我错了,请纠正我。
以下是在工作线程上执行的方法:
Private Sub My_BgWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles My_BGWorker.DoWork
SetLabelText_ThreadSafe(Me.lbl_Status, FormatPercent(i / m_CountTo, 2))
End Sub
我只包含了对这个问题很重要的代码行。如你所见,然后调用我提到的子程序:
Private Sub SetLabelText_ThreadSafe(ByVal lbl As Label, ByVal txt As String)
' InvokeRequired required compares the thread ID of the calling thread to the thread ID of the creating thread.
' If these threads are different, it returns true.
If lbl.InvokeRequired Then
'WORKS: Dim MyDelegate As New SetLabelText_Delegate(AddressOf SetLabelText_ThreadSafe)
'WORKS: Me.Invoke(MyDelegate, New Object() {lbl, txt})
MyDel.Invoke(lbl, txt)
Else
lbl.Text = txt
End If
End Sub
现在您可以看到我已将代码注释掉'WORKS',因为它确实存在,但我很困惑,因为委托MyDel.Invoke(lbl, txt)
时,它会进入无限循环,因为委托是在主要形式声明。
谢谢。
编辑:为了澄清,主表单声明中的代表是:
Dim MyDel As New SetLabelText_Delegate(AddressOf SetLabelText_ThreadSafe)
答案 0 :(得分:4)
当你这样称呼时:
Private Sub SetLabelText_ThreadSafe(ByVal lbl As Label, ByVal txt As String)
If lbl.InvokeRequired Then
MyDel.Invoke(lbl, txt)
在后台主题上,发生了什么:
lbl.InvokeRequired
,True
,因为这不是UI线程Delegate.Invoke
。这有效地调用了方法lbl.InvokeRequired
为真,并调用Delegate.Invoke
- 创建无限循环然而,当你致电Me.Invoke
时,这有点不同。在此上下文中,Me
是表单,因此您正在调用Control.Invoke
,它将调用回调到UI线程。它然后运行,但是在那时,它将在UI线程上运行,因此lbl.InvokeRequired
将是False
,它将只运行一次而不是无限。