【问题标题】:VB form cross thread method call with parametersVB表单带参数的跨线程方法调用
【发布时间】:2016-11-06 19:22:56
【问题描述】:

我正在编写一个 VB 表单应用程序,它重定向进程的标准输出流并在 UI 中使用它。

我在调用带有参数的方法时遇到问题,这些方法会从 OutputHandler 子中更新表单上的控件。

我可以像这样调用不带参数的方法

Me.Invoke(New MyDelSub(AddressOf ServerStarted))

效果很好。

谷歌搜索告诉我,要调用带参数的方法,我应该这样做:

Dim del As JoinDelegate = AddressOf PlayerJoins
del.Invoke(username)

有了这个委托和方法对:

Private Delegate Sub JoinDelegate(ByVal username As String)
Private Sub PlayerJoins(ByVal username As String)
   PlayersBox.Items.Add(username)
   'Do other stuff
End Sub

但这会在该方法第一次尝试访问控件时产生 IllegalOperationException。

【问题讨论】:

  • 该问题已被多次询问和回答。例如看看这篇文章:Cross-Thread operation not valid VB.NET。然而,使用Lambda Expressions 解决问题在语法上可能很有趣。
  • 是的,我阅读了其中的一些,只是无法弄清楚如何使用它来传递参数。对不起,我很愚蠢;)

标签: vb.net multithreading winforms delegates


【解决方案1】:

1)假设你有这样的方法:

Public Sub DoSomething(value1 As String, value2 As String)
    MessageBox.Show(String.Format("{0} {1}", value1, value2))
End Sub

你可以这样调用它:

Me.Invoke(Sub() DoSomething("Hello", "World!"))

2)如果您想对控件进行线程安全调用,您可以这样编写方法:

Public Sub AddItemToListBox1(item As String)
    If (ListBox1.InvokeRequired) Then
        ListBox1.Invoke(Sub() AddItemToListBox1(item))
    Else
        ListBox1.Items.Add(item)
    End If
End Sub

然后在 UI 线程或另一个线程中以相同的方式简单地调用它就足够了:

AddItemToListBox1("some item")

调用将是线程安全的。

【讨论】:

  • 正是我想要的,不敢相信我没有看到如何做到这一点 - 花了几个小时与代表和各种意大利面条代码搞混。谢谢!
  • 不客气 :) - 我相信这是最易读和最干净的方式。
【解决方案2】:

例如

Private Sub SetControlText(control As Control, text As String)
    If control.InvokeRequired Then
        control.Invoke(New Func(Of Control, String)(AddressOf SetControlText), control, text)
    Else
        control.Text = text
    End If
End Sub

从任何线程调用该方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-23
    • 2012-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多