需求 具体描述 (待)实现方式(/ 思路)
图表添加切割线条 添加横向线条来指示每次换卷的截断位置 换卷事件中添加相应处理,并且使用图表控件的对应方法画出线条

先前添加了插件中的换卷事件处理。

换卷的处理函数中修改了数据库,而当该函数被外部插件(监听串口的线程)或者用户按钮事件调用时,如果任务不是处于暂停状态,会与数据处理线程的插入行函数(InsertRow) 产生冲突,两个线程会在相近的时间内访问数据库连接对象,相应的打开和关闭数据库过程会产生异常。

image-20221019160348240

因为涉及到委托调用数据库更新操作,在主程序对数据库进行操作时,可能会出现冲突的情况,因此需要加上数据库的访问锁

1
2
//数据库访问互斥
readonly static object _locker_db = new object();

在创建数据库之后的所有对数据库操作添加如下互斥访问方式

1
2
3
4
5
//互斥访问数据库对象
lock (_locker_db)
{
do();
}

在主程序进行数据库插入时进行检测是否换卷

以上操作无效。

经过大量 debug 跟踪发现,出现异常的原因为数据库连接 Dbcn 对象的连接和断开需要一定时间,在多个线程同时进行访问的时候会出现线程 A 断开连接之后,线程 B 开始连接,但是到执行 sql 语句的时候,连接并没有正确建立,于是出现数据库访问异常。

解决的方式为添加检测数据库连接状态和超时异常检测,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int timeout = 0;
//等待连接打开
while(true)
{
if(Dbcn.State == Connection.State.Open)
break;
if(timeout<=300)
{
timeout += 5;
Thread.Sleep(5);
}
else
{
throw(new DataBaseTimeOutException("Update Time Out!"));
}
}

1
2
3
4
Dbcn.Close();
//等待连接关闭
while (Dbcn.State != ConnectionState.Closed)
Thread.Sleep(5);

这种方式也有局限性,并不能完全防止异常情况发生。但是在缺陷生成速度不是特别快的情况下,应该可以避免数据库连接速度产生的问题。经测试在 0.7/s 的缺陷产生速率时,可以满足数据的记录需求。

上述方案虽然不会产生程序异常,但是可能会存在数据更新不及时的情况:

image-20221019162731880

其中

image-20221019162755350

编号为 9 的数据行没有被正确更新放卷 Y 的数据,推测可能是由于换卷事件执行的时候又有新的缺陷数据被加载到缺陷队列中,此时的卷号还没有修改,因此读取了未被修改的卷号

原先的换卷处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void ReelChange()
{
//数据库操作,该部分可能耗时较久
do();
//插件事件触发器
do();
//卷号增加
nReel++;
//修改卷长
lock (_locker_length)
reelLength = 0;
//目录更新
cfg.SetDics(nReel);
}

修改后的换卷处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void ReelChange()
{
//临时存储先前的卷号
int n = nReel;
//卷号增加
nReel++;
//数据库操作,该部分可能耗时较久
do();
//插件事件触发器
do();
//修改卷长
lock (_locker_length)
reelLength = 0;
//目录更新
cfg.SetDics(nReel);
}

image-20221019163919874

修改之后,数据更新恢复正常。

绘图操作后续更新。