C# 是否向其他类别提供测量数据(从串行端口)?

C# 是否向其他类别提供测量数据(从串行端口)?,c#,.net,data-structures,C#,.net,Data Structures,我有一个通过虚拟COM端口连接的设备。该装置每100ms发送一次测量数据。有多个通道可以单独(取消)激活,这会影响发送哪些数据/哪些通道 目前,我通过类型为Dictionary的事件提供数据。字符串是通道的名称,double是值。第一个“通道”是来自设备的时间戳。需要数据的类只是订阅事件 图表(显示在主窗口中)和某些其他类需要这些数据,这些类偶尔需要最后n个值来执行几项检查(最小值/最大值/平均值…) 当然,我觉得大约每100毫秒触发一次事件是向应用程序的其他部分提供测量数据的一种非常无效的方式

我有一个通过虚拟COM端口连接的设备。该装置每100ms发送一次测量数据。有多个通道可以单独(取消)激活,这会影响发送哪些数据/哪些通道

目前,我通过类型为
Dictionary
的事件提供数据。字符串是通道的名称,double是值。第一个“通道”是来自设备的时间戳。需要数据的类只是订阅事件

图表(显示在主窗口中)和某些其他类需要这些数据,这些类偶尔需要最后n个值来执行几项检查(最小值/最大值/平均值…)

当然,我觉得大约每100毫秒触发一次事件是向应用程序的其他部分提供测量数据的一种非常无效的方式(尤其是重新绘制图表)。这是一个很好的替代方案吗

如果是这样,DataTable对于“未指定”值的行为如何,例如,当给定时间戳的通道未激活(因此,设备未发送)时,数据中存在“漏洞”?想象一下,它可能是这样的

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

还有其他替代方案吗?

在您的示例中,在时间5时,通道1的值为37。在时间6,没有报告通道1的值。你有三个选择:

  • 给它指定一些默认值,或者一个随机值
  • 假设该值与以前的读数没有变化
  • 编写代码,将缺少的值考虑在内,并采取相应的行动
  • 选项1并不是特别有用,尽管如果您给它一个在正常处理中永远看不到的默认值,那么您至少可以看到在这段时间内没有报告任何值

    选项3实际上只是把处理问题的责任推给了下一个排队的人。不过,它确实有保持数据纯净的优势:您没有错误的迹象表明某些数据实际上是在这段时间内传入的

    选项2可以在数据采集时应用,也可以在数据处理时应用。我倾向于在处理时处理它。也就是说,数据表将不包含任何时间段内缺失通道的值。然后,处理数据的每个方法都可以确定如何处理数据

    也就是说,我要警告不要为此使用数据表。我不知道您的代码是否是多线程的,但如果是多线程的,那么您会遇到并发问题,其中一个线程试图更新表,而其他线程则试图读取它

    我建议采用一种方法,让几个不同的类订阅更新事件。每个事件处理程序获取事件并对每个事件进行自己的处理,并保留自己感兴趣的数据副本。这样,每个组件都可以针对特定情况以最佳方式处理缺少数据点的情况

    每100毫秒发生一次事件不会给系统带来沉重的负担,除非您对这些事件进行大量繁重的处理

    对于图形更新程序,我可能会让它在计时器上更新。例如,每秒一次或每500毫秒一次。graphing类将维护自己的数据列表,可能受到锁的保护,它根据传递给它的事件数据填充锁。当计时器触发以更新图表时,代码锁定列表,使其不被更新,绘制图表,然后解锁列表

    对于最小值/最大值/平均值计算,您同样需要维护自己的最近项目列表,并在每个项目进入时更新计算。从最近的
    n
    项中维护运行的最小值/最大值/平均值是一种非常标准的技术,只需要很少的处理

    这样做可能需要更大的内存占用,但不应该太大。事实上,与数据表的每行开销相比,它甚至可能更便宜。其好处是,每个类都以最适合该类功能的格式维护它所需的数据


    我在多年前编写的一个网络爬虫应用程序中使用了这项技术,效果非常好。每个类都会收到下载的每个文档的通知,以及统计信息(所用时间、大小等),每个类都会在屏幕上显示这些信息,让我了解爬虫程序的工作方式。爬虫程序以每秒15个文档的速度下载,因此我以大约每66毫秒一个事件的速度触发事件,而机器在这方面没有问题。

    谢谢,特别是提到通过计时器更新图表。这很可能是最昂贵的操作,每100毫秒执行一次也毫无意义!