我有一台通过虚拟COM端口连接的设备。该设备每100ms发送一次测量数据。有多个通道可以单独(反)激活,这会影响哪些数据/哪些通道被发送。
目前,我通过Dictionary<string, double>
类型的事件提供数据。字符串是通道的名称,double是值。第一个&#34;频道&#34;是设备的时间戳。需要数据的类只是订阅事件。
图表需要数据(在MainWindow中显示)以及其他一些偶尔需要最后n个值来执行多次检查的数据(最小值/最大值/平均值...)。
当然,我觉得大约每100毫秒触发一个事件是一种非常无效的方法,可以将测量数据提供给应用程序的其他部分(尤其是重绘图表)。 DataTable会成为一个很好的选择吗?
如果是这样,DataTable将如何处理&#34;未指定&#34;值,例如当一个给定的时间戳没有激活一个频道(因此,没有被设备发送),所以有&#34;空洞&#34;在数据?要想象,它可能看起来像这样
Time | Ch1 | Ch2 | Ch3 | ...
------+-------+-------+-------+
0 | 34 | | |
1 | 35 | | |
2 | 36 | | |
3 | 35 | | 23 |
4 | 36 | 11 | 26 |
5 | 37 | 13 | 26 |
6 | | 14 | 21 |
7 | | 13 | 25 |
8 | | 16 | |
9 | | 14 | |
10 | | 22 | |
11 | | 24 | |
12 | | 24 | 45 |
13 | 37 | 27 | 44 |
14 | 36 | | 46 |
15 | 35 | | |
16 | 33 | | |
17 | 32 | 30 | |
18 | 23 | 32 | |
还有其他选择吗?
答案 0 :(得分:2)
在您的示例中,在时间5,通道1的值为37.在时间6,没有为通道1报告值。您有三个选择:
选项1并不是特别有用,但如果你给它一个在正常处理中看不到的默认值,那么你至少可以看到在那段时间内没有报告任何值。
选项3真的只是将处理问题的责任推到了下一个人的排队。但是,它确实具有保持数据纯净的优点:您没有错误的迹象表明在此期间实际上有一些数据进入。
选项2可以在数据收集时或数据处理时应用。我的偏好是在处理时处理它。也就是说,数据表在任何时间段内都不包含缺失通道的值。然后,处理数据的每个方法都可以确定如何处理它。
那就是说,我会警告不要使用数据表。我不知道你的代码是否是多线程的,但如果是,那么你会遇到并发问题,一个线程试图更新表,而其他人试图读取它。
我建议使用一种方法,它有几个不同的类订阅更新事件。每个事件处理程序获取事件并对每个事件进行自己的处理,并保留其自己感兴趣的数据的副本。这样,每个单独的组件都可以针对特定情况以最佳方式处理丢失的数据点案例
每100毫秒发生一次事件不会对系统造成沉重负担,除非你对这些事件进行了大量的重负荷处理。
对于图表更新程序,我可能会在计时器上更新它。比如,每秒一次或每500毫秒一次。图形类将维护自己的数据列表,可能受锁的保护,它从传递给它的事件数据中填充。当计时器触发更新图形时,代码会锁定列表以使其不会更新,绘制图形,然后解锁列表。
对于最小值/最大值/平均值计算,您将再次维护自己的最近项目列表,并在每个项目进入时更新计算。维护最近n
个项目的最小/最大/平均值是一种非常标准的技术,只需要很少的处理。
以这种方式做事可能需要更大的内存占用,但它不应该是巨大的。事实上,与数据表的每行开销相比,它甚至可能更便宜。好处是每个类只以最适合该类功能的格式维护它所需的数据。
我在很多年前写过的网络爬虫应用程序中使用了这种技术,并且效果很好。每个类都被通知了下载的每个文档,以及统计信息(花了多长时间,有多大等等),每个类都在屏幕上显示,以便让我了解爬虫的工作原理。爬虫正在以每秒15个文档的顺序下载,所以我以每66毫秒一个的速度发射事件,并且机器没有问题跟上它。