需要有关VB.Net多线程选项的建议

时间:2012-04-25 21:22:30

标签: vb.net multithreading controls richtextbox

美好的一天,

我正在考虑在我当前的工作项目中使用哪种多线程方法。由于我从未在我的生活中编写过多线程应用程序,因此这一切都让人感到困惑和压倒性。不用多说,这是我的背景故事:

我被指派在我的公司R& D实验室接管一个测试设备的控制应用程序。该程序必须能够同时发送和接收与三个不同设备的串行通信。最初的程序是用VB 6编写的(没有多线程),我确实计划对它进行修改以使用需要测试的新产品,直到在测试期间由于过多的串行通信导致用户界面锁定时出现安全隐患。这导致测试仪硬件的一部分爆炸,所以我决定尝试在VB.Net中重写应用程序,因为我开始时更喜欢它,因为我认为多线程可能有助于解决这个问题。

我的计划是从主应用程序线程向其他设备发送命令,并将接收端旋转到自己的线程中,以便在时间关键时主线程不会锁定。但是,我还没有接受我的选择。为了解决我的问题,我需要在收到通信时在单独的富文本框中显示收到的通信,而主程序需要解析来自一个特定设备的数据,但只需要从最新测试中得到的文本(我需要文本框包含所有收到的数据)。

到目前为止,我已经调查了代表,自己处理线程,并开始研究BackgroundWorkers。我今天早些时候试图使用代理,但无法找到更新文本框的方法。我是否需要使用回调函数来执行此操作,因为我无法在委托函数本身中执行此操作?我自己处理线程时遇到的问题是弄清楚如何在线程和程序的其余部分之间来回传递数据。背景工作者,正如我所说,我刚刚开始调查,所以我不知道该怎么想它们。

我还应该注意,该计划是为了生成的线程持续运行,直到某种方式触发停止。这是否可以使用上述任何选项?还有其他我尚未发现的选择吗?

很抱歉我的长度和事实似乎在絮絮叨叨地消失了一些信息,但我正处于一个紧迫的截止日期并且强调到我无法直接思考的地步!任何建议/信息/链接都非常感谢。我只需要帮助权衡选项,这样我就可以选择方向并继续前进。感谢所有花时间阅读这个烂摊子的人!

1 个答案:

答案 0 :(得分:4)

好的,串口,线程间通信,在RichTextBox等GUI组件中显示内容,需要快速解析传入数据以解码协议并激活到状态机。

是否所有三个串口都将进入相同的'processControl'状态机?

如果是这样,那么你应该通过组合事件/数据对象并将它们排队到由一个线程运行的状态机来实现这一点(参见BlockingCollection)。理解/调试比使用互斥锁锁定状态引擎更安全,更容易理解/调试。

定义一个'comms'类来保存数据并将其传送到系统中。它应该有一个'命令'枚举,以便获得一个的线程可以通过打开枚举来做正确的事情。 “事件”成员,可以设置为状态引擎使用的任何内容。一个'bool loadChar(char inChar)',它可以将char-by-char数据抛入其中,并且只有在完整,经过验证的协议单元已经组装,检查并解析为数据队列时才会返回'true'。一种'string textify()'方法,以文本形式转储有关包含数据的信息。用于保存文本内容的常规“状态”字符串。 'errorMess'字符串和Exception成员。

你可能会有这个想法 - 这个comms类可以在系统周围传输任何东西。它被封装,以便线程可以使用它的数据和方法,而无需引用任何其他通信实例 - 它不需要任何锁定。它可以排队等待阻塞集合上的线程和BeginInvoked到GUI线程来显示东西。

在serialPort对象中,在启动时创建通信并使用serialPort实例加载成员。并且,当DataReceived事件触发时,一次从args获取数据并激活到comms.loadChar()。如果loadChar调用返回true,则将comms实例排入状态机输入BlockingCollection,然后立即创建另一个comms并开始用数据加载新的comms。只需继续这样做 - 用chars加载通信实例,直到它们有一个经过验证的协议单元并将它们排队到状态机。可能每个串口都有自己的协议 - 好的,所以你可能需要三个comms后代来覆盖loadChar来正确解码它们自己的协议。

在状态机线程中,只需从输入中获取()comms对象,并使用当前状态和来自comms对象的事件来执行状态引擎事务。如果SM动作例程决定显示某些内容,则使用设置为“displaySomeStuff”的命令将Comms引导到GUI线程。当GUI线程获得通信时,它可以通过命令切换命令来决定显示什么/什么。

无论如何,这就是我构建所有流程控制类型应用程序的方式。数据在“通信”对象实例中围绕系统流动,一次不会有多个通信对象操作任何通信对象。如果转到GUI线程,则通过在BlockingCollection,(或类似),队列或BeginInvoke()上传递消息来完成。

唯一的锁在队列中,因此被封装。根本没有明确的锁。这意味着根本没有明显的死锁。我确实很头疼,但我没有得到锁定。

哦 - 不要靠近'Thread.Join()'。