软件功能
读取OPC,开一个TCP侦听,允许客户端通过我的软件获取OPC的数据
OPCServer是ABPLC的RSLinx,客户端是Unity3D,用OPC的dll会比较麻烦,所以自己做了个中间件
要读取的数据配置到excel表里
软件开启的时候读取excel表,然后放到datatable里
为了方便通信时关联OPC标签和值,我把值也存放在datatable的新增列里去了
同时,又新增了一列”OPC旧值”,这样OPC数据无变化时,可以减少向客户端发送的数据,提高效率
这个datatable是个全局静态变量,定义在program.cs类里,只有在软件开启的时候会add,其他时候仅仅是取出或赋值
一共有3个地方会访问datatable:
1.读取到OPC标签的值之后,更新OPC值
2.客户端通过TCP取数据的时候,取值并拼接到byte数组里,然后用”OPC值”给”OPC旧值”赋值
3.有个窗口可以实时显示这个datatable的结构和值
窗口显示部分,为了避免线程操作UI,我是在打开窗体时先datatable.copy()到一个新的datatable中,再绑定,然后timer里循环判断两个datatable是否有变化,有不同就用全局datatable给局部datatable赋值
这样应该不存在线程不安全的问题才对
但是实际情况是,运行一开始一切正常,运行了一段时间后,datatable里的数据就都窜行了
窜行分两种:
1.整个datatable的顺序都变了,开始我以为是因为观察窗口的datagridview没有禁止排序导致的,但是我在关闭窗口时指定
datagridview.datasource=null,一开始确实可以在排序->关闭->再开之后,恢复默认的排序
但是运行了一段时间后再看,还是会顺序错乱
2.OPC值和OPC旧值对应不上了,整个窜了一行.行号我都是用索引控制的,按理说不应该存在窜行的情况才对
而且在OPC获取到值的回调事件中,有时会报错:索引超出数组界限
传递给OPCdll的是一个ArrayList,这个ArrayList也是在program.cs里定义的全局静态变量,而且是在读文件之后,跟datatable一起初始化的,之后没有代码对它进行任何操作,按理说ArrayList的长度应该跟datatable的行数永远一致才对,而且行数应该永远不变
真伤脑筋