无限循环和交叉线程
我是一名试图自学VB.NET的学生。今天我想解决BackgroundWorker 组件。我在网上找到了一篇很棒的文章: 如何使用后台工作者。我成功地完成了演练,甚至执行了“冒险”部分,该部分涉及使用委托跨线程更新控件。
现在我遇到了一个我不明白它是如何工作的部分。总结以下代码,我有一个委托,其签名中有一个标签和一个字符串。然后我有一个在工作线程上调用的子例程。在这个子例程中,委托被创建并(我猜)再次运行,以便它位于同一个(主)线程上。如果我在这里错了,请纠正我。
这是在工作线程上执行的方法:
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)
I am a student attempting to learn VB.NET on my own. Today I wanted to tackle the BackgroundWorker component. I found an excellent article online: How To Use a Background Worker. I successfully completed the walkthrough and even performed the "adventorous" part that dealt with working with controls updating across threads using delegates.
Now I came to a part that I didn't understand how it was working. To summarize the following code, I have a delegate that has a Label and a String in its signature. I then have a subroutine that is called on the worker thread. Inside this subroutine the delegate is created and (I guess) ran again so that it is on the same (Main) thread. Please correct me if I'm wrong here.
Here is the method is performed on the worker thread:
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
I've only included the line of code that is of importance to this question. As you can see this then calls a subroutine that I mentioned:
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
Now as you can see I have the code commented out 'WORKS' because it does, but I'm confused as why it goes into an infinite loop when the MyDel.Invoke(lbl, txt)
is called because the delegate is created in the Main form Declarations.
Thank you.
EDIT: And for clarification, the delegate in the Main form Declaractions is:
Dim MyDel As New SetLabelText_Delegate(AddressOf SetLabelText_ThreadSafe)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当您调用此方法时:
在后台线程上,发生的情况是这样的:
lbl.InvokeRequired
,这是True
,因为这不是 UI 线程Delegate.Invoke
,它执行委托。这有效地调用了该方法lbl.InvokeRequired
为 true,并调用Delegate.Invoke
-创建无限循环但是,当您调用
Me.Invoke
时,情况有点不同。在这种情况下,Me
是表单,因此您正在调用Control.Invoke
,它将回调编组回 UI 线程。然后它会运行,但此时它将在 UI 线程上运行,因此 lbl.InvokeRequired 将为 False,并且它只会运行一次而不是去无限。When you call this:
On a background thread, what's happening is this:
lbl.InvokeRequired
, which isTrue
, since this is not the UI threadDelegate.Invoke
, which executes the delegate. This effectively calls the methodlbl.InvokeRequired
is true, and callsDelegate.Invoke
- creating the infinite loopHowever, when you call
Me.Invoke
, this is a bit different.Me
, in this context, is the Form, so you're callingControl.Invoke
, which marshals the call back to the UI thread. It then runs, but at that point, it'll be running on the UI thread, solbl.InvokeRequired
will beFalse
, and it'll just run once and not go infinite.