首页 新闻 会员 周边

求大神帮小白解决界面假死情况

0
悬赏园豆:50 [待解决问题]

我是一个小白,现在程序是需求是需要连续采集com口设备的数据,使用Windows.Forms.Timer定时向com口发送命令,然后在Comm_DataReceived里处理数据(包括和数据库交互),并更新界面,这里已经用了BeginInvoke更新UI。
设想的情况是,定义一个公共变量,timer每发送完一次,将公共变量赋值为false,Comm_DataReceived处理完数据后,将公共变量赋值为true,timer判读公共变量为true的话继续发送,为false的时候 不发送
现在遇到的问题就是程序运行一段时间后界面就卡死了,或者数据变化较大的时候也会卡死,请大神指条明路啊,谢谢;

清岚思辰的主页 清岚思辰 | 初学一级 | 园豆:104
提问于:2022-09-22 11:16
< >
分享
所有回答(4)
0

是不是需要加个锁,Comm_DataReceived一般时异步回调的,如果没有锁的话,你的公共变量就会失控

WmW | 园豆:424 (菜鸟二级) | 2022-09-22 11:42

加了lock锁,还是会卡死

支持(0) 反对(0) 清岚思辰 | 园豆:104 (初学一级) | 2022-09-22 11:47

@清岚思辰: 代码方便贴一下吗

支持(0) 反对(0) WmW | 园豆:424 (菜鸟二级) | 2022-09-22 11:49

@WmW: 其实过程并不复杂,请帮忙看看
private static bool inTimer = true;
private void Timer1_Tick(object sender, EventArgs e)
{
lock (ob)
{
if (inTimer)
{
inTimer = false;
//这里发送命令
}
}
}
void Comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
lock(obj)
{
//接收数据并处理
this.BeginInvoke((EventHandler)(delegate
{
//更新界面
}));
inTimer = true;
}
}

支持(0) 反对(0) 清岚思辰 | 园豆:104 (初学一级) | 2022-09-22 12:12

@清岚思辰: 为什么一个锁ob,一个锁obj啊,你的Timer1的频率是多少

支持(0) 反对(0) WmW | 园豆:424 (菜鸟二级) | 2022-09-22 12:40

@WmW: 我打错了,都是obj,频率0.2m

支持(0) 反对(0) 清岚思辰 | 园豆:104 (初学一级) | 2022-09-22 12:56

@清岚思辰: 看上去不是锁的问题,有可能是this.BeginInvoke异步还没执行完,你的inTimer = true了,导致又发送了请求,大量的this.BeginInvoke累计导致卡死了,你把inTimer = true放到this.BeginInvoke内部试试,待更新了Ui后再把inTimer置为true,如果能保证所有的操作执行完毕后再把inTimer=true,那就没必要加锁了

支持(0) 反对(0) WmW | 园豆:424 (菜鸟二级) | 2022-09-22 14:34

@WmW: 测试了一下,放进去还是会卡

支持(0) 反对(0) 清岚思辰 | 园豆:104 (初学一级) | 2022-09-24 16:30

@清岚思辰: 是刚运行就卡,还是随着时间越来越卡,如果是刚运行就卡,很可能是更新界面这块有问题

支持(0) 反对(0) WmW | 园豆:424 (菜鸟二级) | 2022-09-26 09:13
0

你用vs的f5运行会出现卡死现象吗?

会长 | 园豆:12401 (专家六级) | 2022-09-22 13:49

会卡

支持(0) 反对(0) 清岚思辰 | 园豆:104 (初学一级) | 2022-09-24 16:26
0

.net版本如果高的话,可以收到数据后,Task.Factory.New(()=>处理。。。),处理过程中要更新界面的,直接 用Invoke即可。

如果版本低的话,你应该去降频,com有时候回传数据频率非常高,你必然要降。
硬件消息有一种模式是,如果你接收的数据只有最新的有效,那么你就不应该取所有的数据,而是取你需要 的时候最后一个。
你收到数据,把它们放到System.Collections.Concurrent.ConcurrentBag里面,下次来了,把旧的System.Collections.Concurrent.ConcurrentBag里面的覆盖掉。

你再起一个Timer,监控Bag里面的变化,如果有,则用业修改界面,这个Timer的频率是你可控的。

ensleep | 园豆:1682 (小虾三级) | 2022-09-22 16:46
0

死锁了吧 或者是timer重入太快
如果是这样的话 可以在DataReceived开始的时候停到timer 结束后再次启动timer
还有 winform.timer 走的是ui线程 如果是发送指令时候的问题 可以在timer 执行的时候 在另一个线程发指令
愚见 无效勿喷

彭小立 | 园豆:634 (小虾三级) | 2022-09-23 17:26
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册