2012-04-25 44 views
3

好日子所有,需要咨询关于VB.Net多线程选项

我有一个时间地狱搞清楚其多线程的方式在我目前的工作项目,以利用。由于我从未在我的生活中编写过多线程应用程序,这一切都令人困惑,并且非常令人难以置信。简而言之,这里是我的背景故事:

我已被分配接管在我公司的一台测试设备的控制应用程序的工作R & D实验室。该程序必须能够半并发地发送和接收与三个不同设备的串行通信。原来的程序是用VB 6编写的(没有多线程),我的计划只是修改它,以便与需要测试的新产品一起工作,直到由于测试过程中过多的串行通信导致用户界面锁定而导致安全隐患时。这导致测试器硬件的一部分被炸毁,所以我决定尝试在VB.Net中重写应用程序,因为我更喜欢它,因为我认为多线程可能有助于解决这个问题。

我的计划是从主应用程序线程向其他设备发送命令,并将接收端关闭到自己的线程中,以便在计时非常关键时主线程不会锁定。不过,我还没有接受我的选择。为了补充我的问题,我需要在接收到的通信信息时使用单独的富文本框来显示接收到的通信信息,而来自某个特定设备的数据需要由主程序进行分析,但仅限于最新测试的结果(我需要文本框来包含所有收到的数据)。

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

我还应该注意,该计划是为了产生的线程连续运行,直到以某种方式触发停止。这可能与以上任何选项?我还没有发现其他选项吗?

对不起,我似乎在漫无边际的信息,但我在一个紧迫的最后期限,并强调到我不能认为直的点!任何建议/信息/链接超过赞赏。我只需要帮助权衡选项,以便我可以选择一个方向并继续前进。感谢大家花时间阅读这个烂摊子!

+0

你用串口应用程序炸毁硬件?真棒! +1只是为了防火! – 2012-04-25 21:24:57

+0

是的,测试仪接收到串行命令,告诉它打开和关闭特定的继电器。那么,一个继电器通过一个负载库产生一个热短路,并且只能在一秒之内间隔启动。当UI锁定时,BOOM! ;-) – Jacob 2012-04-25 21:28:16

+0

Windows不是[实时系统](http://stackoverflow.com/tags/real-time/info),因此您可以编写一个多线程程序,它能够成功通过您可以实现的每个测试,但仍然能够以随机的速度炸毁东西;) – GSerg 2012-04-25 21:48:55

回答

4

好吧,串口,线程间通信,在像RichTextBox这样的GUI组件中显示东西,需要快速解析传入的数据来解码协议,并触发状态机。

所有三个串行端口是否会触发到同一个'processControl'状态机?

如果是这样,那么您应该通过组装事件/数据对象并将它们排队到由一个线程运行的状态机(请参阅BlockingCollection)来做到这一点。这与使用互斥锁来锁定状态引擎类似,更安全,更易于理解/调试。

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

您可能会明白 - 这个comms类可以在系统中传输任何东西。它被封装,以便线程可以使用它的数据和方法,而无需引用任何其他通信实例 - 它不需要任何锁定。它可以排队等待Blocking Collection和BeginInvoked的线程到GUI线程显示内容。

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

在状态机线程中,只需从输入中获取()comms对象并使用当前状态和comms对象中的Event来执行状态引擎。如果SM操作例程决定显示某些内容,则使用设置为'displaySomeStuff'的命令开始将通信调用到GUI线程。当GUI线程获得通信时,它可以切换命令来决定显示什么。

无论如何,这就是我建立我的所有过程控制类型的应用程序。数据在'comms'对象实例中围绕系统流动,一次不会有超过一个的com对象操作。这一切都是通过BlockingCollection(或类似的),队列或BeginInvoke()上的消息传递完成的,如果转到GUI线程的话。

唯一的锁在队列中,因此被封装。根本没有明确的锁。这意味着根本没有明确的僵局。我的确头疼,但我没有锁定。

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

+1

太棒了!如果我有这样的声望,我会愿意的。好消息是,我现在有一个非常淡化的形式,所以在你的概念中工作不应该有太多的问题。现在,如果我可以得到这个线程业务的处理,我可能是危险的!谢谢大家! – Jacob 2012-04-26 00:13:35

+0

显然有一些点我错过了 - 没什么严重的,你将不得不填补空白,如果我有机会,我会编辑什么我可以想到以后。 – 2012-04-26 07:53:53