从工作线程更新 UI 表单 [英] Update UI form from worker thread

查看:26
本文介绍了从工作线程更新 UI 表单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am new to multi-threading in VB.NET and have come across a problem whereby I am wanting to append text to a text box on a form from a service thread running in the background.

我正在开发的应用程序是一个客户端/服务器侦听器,我已经能够让客户端和服务器 PC 相互交谈(通过 MsgBox 确认),但是我现在正在努力在服务器上获取服务线程将文本附加到文本框,不会发生任何可见的事情.

The application I am developing is a client/server listener, I have been able to get the client and server PC's to talk with each other (confirmed through MsgBox), however I am now struggling to get the service thread on the server to append the text to the textbox, nothing vissible occurs.

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

I have a form named testDebug which calls a class (RemoteSupport), this class does all the handshake tasks and updates the textbox with the connection data.

谁能指出我哪里出错并指出我正确的方向?

Can anyone identify where I am going wrong and point me in the right direction?

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

The following is the code I have: The form has a textbox named txtOutput, the following is from the remoteSupport class

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

我不确定 invoke 方法是否是理想的解决方案,或者自定义事件是否是理想的解决方案,我花了一些时间尝试让自定义事件起作用,但这些也不起作用.

I am not sure if the invoke method is the ideal solution or if custom events are, I have spent some time on trying to get custom events to work, but these didnt work either.

 // 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

所提供的代码已被删减,所以如果您还有什么想看的或有任何问题,请告诉我.

The code supplied has been cut down so if there is anything else that you want to see or any questions please let me know.

感谢您的帮助.

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

I have uploaded the two VB files (form and class) to my site, I would appreciate it if someone could have a look at it to help me with identifying the problem with the UI not updating.

我尝试了其他一些方法,但是一旦工作线程启动,UI 似乎没有任何更新.

I have tried a few other things but nothing seems to be updating the UI once the worker thread has started.

格式:mulholland.it/testDebug.vb.txt类:mulholland.it/remoteSupport.vb.txt

Form: mulholland.it/testDebug.vb.txt Class: mulholland.it/remoteSupport.vb.txt

感谢您的帮助.

马特

推荐答案

我有一个名为 testDebug...

I have a form named testDebug...

If testDebug.InvokeRequired Then

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

This is a classic trap in VB.NET programming. Set a breakpoint on the If statement. Notice how it returns False, even though you know that the code is running on another thread?

InvokeRequired 是 Form 的一个实例属性.但是 testDebug 是一个类名,而不是对 testDebug 类型形式的实例的引用.这在 VB.NET 中是可能的,这让很多 VB.NET 程序员陷入了深深的麻烦.这是从 VB6 延续下来的时代错误.当您在线程中执行此操作时,它会完全分崩离析并在您的脸上炸开.您将获得一个 new 表单实例,而不是用户正在查看的实例.一个不可见的,因为它的 Show() 从未被调用过.否则就会像门钉一样死掉,因为线程没有运行消息循环.

InvokeRequired is an instance property of a Form. But testDebug is a class name, not a reference to an instance of a form of type testDebug. That this is possible in VB.NET has gotten a lot of VB.NET programmers in deep trouble. It is an anachronism carried over from VB6. It completely falls apart and blows up in your face when you do this in a thread. You'll get a new instance of the form, instead of the one that the user is looking at. One that isn't visible because its Show() was never called. And otherwise dead as a doornail since the thread isn't running a message loop.

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

I answered this question several times already, with the recommended fix. I'll just refer you to them rather than rehashing it here:

在表单之间访问控件

这篇关于从工作线程更新 UI 表单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆