WPF 调用 ECAN 发送数据会阻塞的解决过程
接了个活, 写个 WPF 上位机用 PCAN 或 ECAN 和单片机通讯, 读取传感器数据.
程序逻辑是 : 选择连接类型 PCAN / ECAN, 选择波特率, 选择通道号, 输入查询间隔, 连接设备. 然后开启一个后台线程循环发送读取指令逐个读取传感器数据.
使用 PCAN 时, 连接和收发数据都正常, 但改为 ECAN 连接后, 有很大几率卡在 SDK 的发送函数那.
查看厂商提供的 WinForm demo ,有调用界面定时器来收发数据和在后台开线程来收发数据两种, 我把在后台开线程收发的 Demo 改成了程序的收发逻辑, 测试发现也会卡在SDK的发送函数那里, 我就把在线程里收发数据改成了调用 UI 线程收发数据
1 Dim result As Boolean 2 MainWindowInstance.Dispatcher.BeginInvoke(Sub() 3 result = Ecan.Transmit(1, 0, AppSettingHelper.CANChanelId, sendMsg, 1) = Ecan.ECANStatus.STATUS_OK 4 SendOrReceiveEvent.Set() 5 End Sub) 6 SendOrReceiveEvent.WaitOne(1000) 7 Return result
能正常收发数据, 不会卡在发送函数那, 算是初步解决了问题, 然后就打包发给甲方使用了.
之后咨询了设备厂商, 厂商那边也没有提供解决方法.
过了一段时间, 甲方反馈说单片机没返回数据软件就会死机.
添加日志输出, 看到软件一直在调用接收函数, 然后想起在后台线程里, 写的逻辑是发送读指令后, 尝试接收数据 1000 次, 超过 1000 次失败后就在界面显示当前传感器数据接受失败, 然后继续读取下一个传感器数据.
找到原因后, 就直接把 AutoResetEvent 的 WaitOne 超时改成 10 ms (因为单次数据收发耗时都在 1 ms内)
测试时界面显示 接收传感器数据失败, 就还原修改, 添加 Stopwatch 测试发送函数耗时.
发现连接设备后第一次发送数据耗时大约 500 ms, 之后的发送耗时都在 1 ms内.
然后我就用了一个笨方法, 加个变量来判断是否是连接后第一次发送数据, 是连接后第一次发送就超时 1000 ms, 否则超时 10 ms.
改完后甲方说了一句是不是初始化的问题
因为用 PCAN 连接时, 没有出现这种问题, 这两个设备最大的差异就是 PCAN 价格1500多, ECAN只有 400多.
我就在连接设备后延时了 1000 ms, 然后按最开始的逻辑在后台线程收发数据.
测试几次后发现 SDK 的发送函数不会再阻塞了.
最终原因是 ECAN 设备初始化比 PCAN 设备时间要长, 但没想到未初始化完成就会一直卡在 SDK 的发送函数那