2016-11-06 54 views
1

我正在写一个VB窗体应用程序,它重定向一个进程的标准输出流并在UI中使用它。VB窗体交叉线程方法调用参数

我无法通过参数更新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的该方法第一次尝试访问控件。

+0

该问题已被问及多次回答。例如,看看这篇文章:[跨线程操作无效的VB.NET](http://stackoverflow.com/questions/1331009/cross-thread-operation-not-valid-vb-net)。但是,使用[Lambda Expressions](https://msdn.microsoft.com/en-us/library/bb531253.aspx)来解决问题可能在语法上很有趣。 –

+0

是的,我通读了其中的一些,只是无法弄清楚如何使用它来传递参数。对不起,愚蠢;) – JHall

回答

1

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

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

2)如果你想线程安全:

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

可以使用调用此方法调用它调用一个控件,你可以用这种方法编写该方法:

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") 

的调用将是线程安全的。

+0

正是我想要的,不敢相信我没有看到如何做到这一点 - 花了几个小时与代表和各种意大利面代码搞乱。 谢谢! – JHall

+0

不客气:) - 我相信这是最可读和最干净的方式。 –

0

E.g.

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 

从任何线程调用该方法。