vb.net - 根据另一个类 VB.nET 的线程引发的事件更新 GUI 项目

标签 vb.net event-handling multithreading

如何使用另一个类的线程接收的消息更新 GUI 中的数据?

我有一个带有从服务器接收数据的线程的类。每当该线程从服务器收到消息时,就会引发一个事件。该事件在 Starter Class(包含 GUI 的主类)内处理。 事件处理程序(例如 DisplayData())必须显示其他类收到的消息。 我的代码是这样的

Class GUI
    receiverObj = New Receiver()
    Addhandler receiverObj.MessageAlert, Addressof DisplayData
    ...
    ...
    Sub DisplayData()
        Dim str As receiverObj.ReceiveData

        lbEvents.Add.Items(str)   ' lbEvents is a ListBox inside the GUI that displays messages from Receiver 
    End Sub
End Class


Class Receiver

    Public Event MessageAlert()
    Sub New ()
        MyTcpClient = New TcpClient(hostIP, port)               
        MyTcpClient.GetStream.BeginRead(ReceiveData, 0, PacketSize, AddressOf ReceiveStream, Nothing)
    End Sub

    Public Sub ReceiveStream(ByVal ar As IAsyncResult)
        Dim ByteCount As Integer

        Try
            ByteCount = MyTcpClient.GetStream.EndRead(ar)
            Dim t As New Threading.Thread(Sub() RaiseEvent MessageAlert())
            MyTcpClient.GetStream.BeginRead(ReceiveData, 0, PacketSize, AddressOf ReceiveStream, Nothing)
     End Sub
End Class

窗口崩溃或挂起,并且列表框不显示数据。抛出异常说

跨线程操作无效:控制 xxx 从创建它的线程以外的线程访问。

有人可以提出解决此错误的方法吗? 如何使用另一个类的线程接收的消息更新 GUI 中的数据?

最佳答案

对 Windows 应用程序 GUI 元素的更新必须在创建 GUI 的线程上进行。

为了解决这个问题,有一个名为 Invoke 的方法,它允许您触发一个委托(delegate),该委托(delegate)可以确保控制权传递给 GUI 线程并执行您正在尝试的更新。

您需要一些东西才能完成这项工作:

  1. 委托(delegate)类型,例如

    Delegate Sub MyGUIUpdateDelegate()
  2. 委托(delegate)类型的变量

    Public myGUIUpdateDelegate as MyGUIUpdateDelegate
  3. 具有与委托(delegate)匹配的签名并执行工作的方法:

    Public Sub MyGuiEventHandler()<br/>
            ' Do work on proper GUI thread, via Control.Invoke,
            ' such as listbox population<br/>
            If (Me.InvokeRequired) Then
                Me.Invoke( myGUIUpdateDelegate)
            Else
                // do control specific work, we're on the GUI thread here
            End If<p></p>
    
    

    End Sub

  4. 将事件处理程序分配给您的委托(delegate):

    myGUIUpdateDelegate = New MyGuiUpdateDelegate(AddressOf myForm.MyGuiEventHandler)
  5. 通过 Control.Invoke 从事件线程调用更新程序方法到正确的线程(假设 您的表单实例变量名为 myForm):

    myForm.Invoke(myForm.myGUIUpdateDelegate);

这至少是一个可以帮助您入门的框架。这个想法是,想要引发更新的后台线程不应该(并且实际上不能)进行直接 GUI 更新。启动到 GUI 线程的上下文切换的正确方法是调用 Invoke 方法来调用正确 GUI 线程上的 GUI 更新程序。

此外,如果您需要将参数传递给委托(delegate),只需更改您定义的委托(delegate)的签名以包含参数,并修改 Invoke 方法以在处理程序中提供参数,并将第二个参数提供给调用。

希望这有帮助。

关于vb.net - 根据另一个类 VB.nET 的线程引发的事件更新 GUI 项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12503532/

相关文章:

.net - 数据表逐列添加而不是逐行添加

javascript - 如何让 Blur 事件为 iPhone 上的文档触发?

c# - 具有 lambda 格式的 Visual Studio 自动完成事件处理程序

JAVA将方法从外部类传递到ThreadPool.submit()

mysql - 我想使用backgroundworker和datagridview显示mysql数据

vb.net - Visual Studio VB.NET 项目中的 “My Project” 文件夹是什么?

c# - 从另一个类中的另一个线程更新文本框内容。 C#、WPF

c++ - 写同步读成功

vb.net - Vb.Net Datagridview错误处理

javascript - bool 函数来了解鼠标按钮的位置