从工作线程更新UI表单

时间:2010-10-20 16:28:04

标签: vb.net

我是VB.NET中的多线程新手,遇到了一个问题,我希望在后台运行的服务线程中将文本附加到表单上的文本框中。

我正在开发的应用程序是一个客户端/服务器监听器,我已经能够让客户端和服务器PC相互通信(通过MsgBox确认),但是我现在正努力在服务器上获取服务线程将文本附加到文本框中,没有任何可变的发生。

我有一个名为testDebug的表单,它调用一个类(RemoteSupport),该类执行所有握手任务并使用连接数据更新文本框。

任何人都可以确定我出错的地方并指出我正确的方向吗?

以下是我的代码: 表单有一个名为txtOutput的文本框,以下内容来自remoteSupport类

Dim outMessage As String = (encoder.GetString(message, 0, bytesRead))
 MsgBox(outMessage, MsgBoxStyle.Information, "MEssage Received")
  If outMessage IsNot Nothing Then
    If testDebug.InvokeRequired Then
        ' have the UI thread call this method for us
        testDebug.Invoke(New UpdateUIDelegate(AddressOf HandleClientComm), New Object() {outMessage})    '
    Else
       testDebug.txtOutput.AppendText(outMessage)
    End If

    'RaiseEvent MessageReceived(outMessage) // a previous attempt to use custom events
 End If

我不确定调用方法是否是理想的解决方案,或者如果自定义事件是,我花了一些时间尝试让自定义事件工作,但这些也没有用。

 // In the RemoteSupport class
 Public Delegate Sub MessageReceivedHandler(ByVal message As String)
 Public Shared Event MessageReceived As MessageReceivedHandler

// Located throughout the RemoteSupport class where debug information is required.
RaiseEvent MessageReceived(outMessage)

// Located in the code-behind of the form
Private Sub Message_Received(ByVal message As String)
testDebugOutput(message) // this is a function I have created 
                         // to append the text to the text box
End Sub

所提供的代码已被删除,所以如果您还有其他想要查看或有任何问题,请告诉我们。

感谢您的协助。

编辑:我已将两个VB文件(表单和类)上传到我的网站,如果有人可以查看它以帮助我识别UI未更新的问题,我将不胜感激。

我尝试过其他一些东西,但是一旦工作线程启动,似乎没有任何东西更新UI。

表格:mulholland.it/testDebug.vb.txt 分类:mulholland.it/remoteSupport.vb.txt

感谢您的协助。

马特

2 个答案:

答案 0 :(得分:6)

  

我有一个名为testDebug的表单......

If testDebug.InvokeRequired Then

这是VB.NET编程中的经典陷阱。在If语句上设置断点。注意它是如何返回False的,即使你知道代码在另一个线程上运行了吗?

InvokeRequired是Form的实例属性。但是testDebug是类名,而不是对testDebug类型的实例的引用。这在VB.NET中是可能的,已经让很多VB.NET程序员陷入了困境。这是从VB6延续出来的一个时代错误。当你在一个线程中执行此操作时,它会彻底崩溃并在你的脸上爆炸。您将获得表单的 new 实例,而不是用户正在查看的实例。一个不可见,因为它的Show()从未被调用过。因为线程没有运行消息循环,否则就像死亡一样死了。

我已经多次回答了这个问题,推荐修复。我只会把你推荐给他们而不是在这里重复:

答案 1 :(得分:0)

Delegate方法可能是您想要的方式,但我没有看到UpdateUIDelegate的声明

我相信你的代码看起来应该是这样的(假设你有一个对你的remotesupport类本地的testdebug表单的引用

Dim outMessage As String = (encoder.GetString(message, 0, bytesRead))
MsgBox(outMessage, MsgBoxStyle.Information, "MEssage Received")
If outMessage IsNot Nothing Then
    If testDebug.InvokeRequired Then
        ' have the UI thread call this method for us
        testDebug.Invoke(New MessageReceivedHandler(AddressOf Testdebug.Message_Received), New Object() {outMessage})   
    Else
        testDebug.txtOutput.AppendText(outMessage)
    End If
end if