如何从工作线程/类更新GUI线程/类? - c#

这里的第一个问题,大家好。

我正在研究的需求是一个小型测试应用程序,该应用程序通过串行端口与外部设备进行通信。通信可能会花费很长时间,并且设备可能会返回各种错误。

该设备在其自己的类中很好地抽象了,GUI线程开始在其自己的线程中运行,并具有通常的打开/关闭/读取数据/写入数据基本功能。 GUI也非常简单-选择COM端口,打开,关闭,显示从设备读取的数据或错误,允许修改和写回等。

问题是,如何从设备类更新GUI?设备处理几种不同类型的数据,因此我需要在GUI表单/线程类与工作设备类/线程之间建立一个相对通用的桥梁。在GUI到设备的方向上,所有操作都可以通过[Begin]调用各种GUI生成的事件上的打开/关闭/读取/写入等调用。

我已经阅读了线程here (How to update GUI from another thread in C#?),其中假定GUI和工作线程在同一类中。 Google搜索抛出了如何创建委托或如何创建经典背景工作者的方法,但这并不是我所需要的,尽管它们可能是解决方案的一部分。那么,有没有可以使用的简单但通用的结构?

我的C#水平中等,我一直在编程我的整个工作生涯,有一个线索我会弄清楚(然后回发)...预先感谢您的帮助。

c#大神给出的解决方案

您可以在UI类上公开一个公共方法,该设备类可以使用需要传递给UI的所有信息在后台线程上调用该方法。该公共方法将在后台线程的上下文中执行,但是由于它属于UI类,因此您现在可以使用已阅读的任何调用封送处理技术。

因此,最简单的设计将是:

在您的UI类(例如MyUIForm)中添加一个称为UpdateUI()之类的方法,该方法将使用您正在使用的任何数据结构来将数据从设备传递到您使用的UI。如果您以后想要支持DI / IoC,并可以通过表格来实现,则可以在接口中声明该方法(例如IUIForm)。
在线程A(UI线程)上,您的UI类创建设备类,初始化所有必需的设置并启动其后台线程。它还传递一个指向自身的指针。
在线程B上,设备收集数据并调用MyUIForm.UpdateUI()(或IUIForm.UpdateUI())。
UpdateUI根据需要执行InvokeBeginInvoke

注意,这具有将所有UI和表示逻辑封装在UI类中的副作用。您的设备类现在可以专注于处理硬件。

更新:为了解决您的可扩展性问题-

无论您的应用程序增长了多少,拥有多少UI类,您仍然希望使用BeginInvoke跨线程边界来更新要更新的特定UI类。 (该UI类可能是特定控件或特定视觉树的根,这并不重要)。主要原因是,如果您有多个UI线程,则必须确保在该线程上发生任何UI更新由于Windows消息传递和Windows的工作方式,因此创建了这个特殊的UI。因此,跨越边界线程的实际逻辑应封装在UI层中。

设备类不必关心需要更新哪些UI类和哪个线程。实际上,我个人将使设备完全不了解任何UI,而只是在其上公开不同UI类可以订阅的事件。

请注意,替代解决方案是使线程完全封装在设备类中,并使UI不知道是否存在免费线程。但是,然后线程边界跨越就成为设备类的责任,并且应包含在设备逻辑中,因此,您不应该使用UI跨越线程的方式。这也意味着您的设备类已绑定到特定的UI线程。

LeetCode题解计算机为什么是基于二进制的?

可以是三进制么?二进制有什么好处?题解:为什么叫电子计算机?算盘应该没有二进制

LeetCode题解统计城市的所有灯泡

这个是我刚毕业的时候,一个真实的面试题,这是一个开放题。题目描述:想办法,将一个城市的所有灯泡数量统计出来。题解:费米估算法1、如果某个城市常驻人口有1000万2、假设每5人居住在一套房里,每套房有灯泡5只,那么住宅灯泡共有1000万只3、假设公众场所每10人共享一只灯泡,那么共有100万只4、主要的这两者相加就得出了1100万只当然实际上这是估算的,具体应…

LeetCode题解黑白圆盘

一个圆盘被涂上了黑白二色,两种颜色各占一个半圆。圆盘以一个未知的速度、按一个未知的方向旋转。你有一种特殊的相机可以让你即时观察到圆上的一个点的颜色。你需要多少个相机才能确定圆盘旋转的方向?题解:可以用一个相机即可

LeetCode题解圆上任取三点构成锐角三角形的概率

来自字节跳动的一道几何题题解:1/4

LeetCode题解深度优先遍历和回溯的关系?

深度优先遍历的范围更大还是回溯的范围更大?为什么?题解:我的理解是:dfs是回溯思想的一种体现- 回溯:是在整个搜索空间中搜索出可行解,在搜索过程中不断剪枝回退,这是回溯的思想,这个搜索空间并没有限制于特定的数据结构。- dfs:dfs是指特定的数据结构中如图,树(特殊的图)中搜索答案,范围限制在了特定的数据结构。个人拙见。