VB.net 从其他线程更新标签

VB.net updating label from other thread

我可能已经阅读并尝试了一百种不同的方法来做到这一点,但我再也受不了了,也无法绕过它。我是多线程的新手,通常使 UI 处理代码。随着我的程序的增长,我发现了我的方法的错误。现在我有 classes 和一个不 lag-out/freeze 主线程 UI 的线程。

从那个 class 我正在尝试更新主窗体上的标签。 (取得了哪些进展)

相关代码如下:

主窗体上有一个名为 UpdateLabel 的标签

主窗体上的一个按钮:

Private Sub btnStartMenu_Click(sender As Object, e As EventArgs) Handles 
btnStartMenu.Click
    Call New Action(AddressOf setupthread1).BeginInvoke(Nothing, Nothing)
End Sub 'creates a new thread which runs great, not freezing the UI!


Private Sub setupthread1()    'this code is still on the main form
                              'all of the label updates work fine from here.
 StartMenu_Folders.startMenuFolders()  'This is the class that gets called 
                                       'from the main form

Public Class StartMenu_Folders
    Public Shared Sub startMenuFolders()
              frmMenu.UpdateLabel(frmMenu.lblLogoff, "...Updating Label text")    'this code is probably incorrect? Though the updatelabel DOES get 
       'successfully called



'This next part is back on the main form.
Public Sub UpdateLabel(ByVal lblLogoff As Label, ByVal Value As String)
    If lblLogoff.InvokeRequired Then
        Dim dlg As New UpdateLabelDel(AddressOf UpdateLabel)
        dlg.Invoke(lblLogoff, Value)
    Else
        lblLogoff.Text = Value
    End If
End Sub

任何帮助将不胜感激,这可能是你们其中一位高级编码员的 2 秒解释。

此时看起来线程 运行 完全没有冻结,但标签只是没有更新。 .谢谢你。 非常感谢!

========================== 根据提供的信息将编辑更新为代码。

来自像您这样的观众! 提示阅读彩虹音乐

'This is all on Main form 'frmMenu'
'Improved way of starting the class in a new thread
Private Sub btnStartMenu_Click(sender As Object, e As EventArgs) Handles btnStartMenu.Click
    Dim t As Task = Task.Run(Sub()
StartMenu_Folders.startMenuFolders()
  End Sub)
End Sub

Public Delegate Sub UpdateLabelInvoker(ByVal text As String)

Public Sub UpdateLabel(ByVal text As String)
    If Me.lblLogoff.InvokeRequired Then
        Me.lblLogoff.Invoke(New UpdateLabelInvoker(AddressOf UpdateLabel), _
                           text)
        MsgBox("invoked")
    Else
        Me.lblLogoff.Text = text
        MsgBox("DIDNT invoke")
    End If
End Sub

    'This is all in the class

Public Class StartMenu_Folders
Public Shared Sub startMenuFolders()
frmMenu.UpdateLabel("testtestest")
End Sub
End Class
'This code is still creating a separate instance of frmMenu I believe.
'I'm not sure how to target the right thread to update the label. 
'I've tried me.UpdateLabel("testtesttest") to no avail.

如果有人知道该怎么做,那就太好了!其他一切都在顺利进行。令人遗憾的是,从另一个线程更新表单上的标签是我在这个程序的几个月里不得不跳过的最难的环节。

您不对委托调用 Invoke 并传递 Label。您在 Label 上调用 Invoke 并传递委托:

lblLogoff.Invoke(dlg, Value)

看我的解释和例子here

编辑:

好的,我想这次我已经掌握了它。这个:

Public Class StartMenu_Folders
    Public Shared Sub startMenuFolders()
              frmMenu.UpdateLabel(frmMenu.lblLogoff, "...Updating Label text")    'this code is probably incorrect? Though the updatelabel DOES get 
       'successfully called

变成这样:

Public Class StartMenu_Folders

    Public Shared Sub startMenuFolders(menuForm As frmMenu)
        menuForm.UpdateLabel("...Updating Label text")

这个:

StartMenu_Folders.startMenuFolders()

变成这样:

StartMenu_Folders.startMenuFolders(Me)

这个:

Public Sub UpdateLabel(ByVal lblLogoff As Label, ByVal Value As String)
    If lblLogoff.InvokeRequired Then
        Dim dlg As New UpdateLabelDel(AddressOf UpdateLabel)
        dlg.Invoke(lblLogoff, Value)
    Else
        lblLogoff.Text = Value
    End If
End Sub

变成这样:

Public Sub UpdateLabel(ByVal Value As String)
    If lblLogoff.InvokeRequired Then
        Dim dlg As New UpdateLabelDel(AddressOf UpdateLabel)
        lblLogoff.Invoke(dlg, Value)
    Else
        lblLogoff.Text = Value
    End If
End Sub

以后,请不要 post 将来自两个不同 类 的代码放在同一块中,因为它会在这里造成混淆。如果您有两个 类,那么 post 代码来自两个不同的块。