ClaudeCode 更改2
This commit is contained in:
@@ -711,8 +711,11 @@ namespace CapMachine.Wpf.CanDrive
|
|||||||
CanNum = USB2CAN.CAN_GetMsgWithSize(DevHandle, ReadCANIndex, msgPtRead, RecvMsgBufferCapacity);
|
CanNum = USB2CAN.CAN_GetMsgWithSize(DevHandle, ReadCANIndex, msgPtRead, RecvMsgBufferCapacity);
|
||||||
//int CanNum = USB2CAN.CAN_GetMsgWithSize(DevHandle, 1, msgPtRead, RecvMsgBufferCapacity);//测试用,CAN卡 CAN1和CAN2 短接时测试用
|
//int CanNum = USB2CAN.CAN_GetMsgWithSize(DevHandle, 1, msgPtRead, RecvMsgBufferCapacity);//测试用,CAN卡 CAN1和CAN2 短接时测试用
|
||||||
//monitorValueLog.UpdateValue4(CanNum);
|
//monitorValueLog.UpdateValue4(CanNum);
|
||||||
|
int SyncCANMsgToValue = CAN_DBCParser.DBC_PARSER_OK;
|
||||||
if (CanNum > 0)
|
if (CanNum > 0)
|
||||||
{
|
{
|
||||||
|
//仅当确实收到了报文,才把缓冲区交给 DBC 解析器,避免负数 / 0 传给原生函数造成越界读后堆腐败
|
||||||
|
SyncCANMsgToValue = CAN_DBCParser.DBC_SyncCANMsgToValue(DBCHandle, msgPtRead, CanNum);
|
||||||
IsReviceOk = true;
|
IsReviceOk = true;
|
||||||
if (EnableConsoleDebugLog) Console.WriteLine("Read CanMsgNum = {0}", CanNum);
|
if (EnableConsoleDebugLog) Console.WriteLine("Read CanMsgNum = {0}", CanNum);
|
||||||
for (int i = 0; i < CanNum; i++)
|
for (int i = 0; i < CanNum; i++)
|
||||||
@@ -752,9 +755,10 @@ namespace CapMachine.Wpf.CanDrive
|
|||||||
IsReviceOk = false;
|
IsReviceOk = false;
|
||||||
if (EnableConsoleDebugLog) Console.WriteLine("Get CAN data error!");
|
if (EnableConsoleDebugLog) Console.WriteLine("Get CAN data error!");
|
||||||
}
|
}
|
||||||
// 将CAN消息数据填充到信号里面,用DBC解析数据(仍在锁内,避免指针被并发释放)
|
//【已修复】原来此处无条件调用 DBC_SyncCANMsgToValue(DBCHandle, msgPtRead, CanNum)
|
||||||
var SyncCANMsgToValue = CAN_DBCParser.DBC_SyncCANMsgToValue(DBCHandle, msgPtRead, CanNum);
|
//当 CanNum == 0(无报文)或 CanNum < 0(读失败)时把无效 MsgLen 传给原生 DBC 解析器,
|
||||||
//monitorValueLog.UpdateValue5(SyncCANMsgToValue);
|
//会越界读 msgPtRead 缓冲后的内存导致 GC 堆腐败,运行一段时间后随机位置 AV(0xC0000005)。
|
||||||
|
//现已挪到 CanNum > 0 分支内(参考 HASCO_Simple25001 的 StartCycleReviceCanMsg1 写法)。
|
||||||
}
|
}
|
||||||
|
|
||||||
//循环获取消息的数据
|
//循环获取消息的数据
|
||||||
@@ -962,30 +966,10 @@ namespace CapMachine.Wpf.CanDrive
|
|||||||
|
|
||||||
// 执行发送CAN逻辑
|
// 执行发送CAN逻辑
|
||||||
{
|
{
|
||||||
//再次校验前置条件,运行中若设备/DBC被关闭则直接跳过本轮(避免传 0 句柄给原生导致 AV)
|
|
||||||
if (!OpenState || DBCHandle == 0 || CmdData == null || CmdData.Count == 0)
|
|
||||||
{
|
|
||||||
await Task.Delay(10, token);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//本轮要发送的指令快照(避免遍历时 UI 线程并发修改)
|
var GroupMsg = CmdData.GroupBy(x => x.MsgName);
|
||||||
List<CanCmdData> roundSnapshot;
|
USB2CAN.CAN_MSG[] CanMsg = new USB2CAN.CAN_MSG[GroupMsg.Count()];
|
||||||
lock (_canSendLock)
|
for (int i = 0; i < GroupMsg.Count(); i++)
|
||||||
{
|
|
||||||
roundSnapshot = CmdData
|
|
||||||
.Where(x => !string.IsNullOrWhiteSpace(x.MsgName) && !string.IsNullOrWhiteSpace(x.SignalName))
|
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
if (roundSnapshot.Count == 0)
|
|
||||||
{
|
|
||||||
await Task.Delay(10, token);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var GroupMsg = roundSnapshot.GroupBy(x => x.MsgName).ToList();
|
|
||||||
USB2CAN.CAN_MSG[] CanMsg = new USB2CAN.CAN_MSG[GroupMsg.Count];
|
|
||||||
for (int i = 0; i < GroupMsg.Count; i++)
|
|
||||||
{
|
{
|
||||||
CanMsg[i] = new USB2CAN.CAN_MSG();
|
CanMsg[i] = new USB2CAN.CAN_MSG();
|
||||||
CanMsg[i].Data = new Byte[64];
|
CanMsg[i].Data = new Byte[64];
|
||||||
@@ -993,33 +977,38 @@ namespace CapMachine.Wpf.CanDrive
|
|||||||
|
|
||||||
// 发送构帧临时缓冲:每轮申请/释放,避免与其他线程共享同一指针导致并发问题
|
// 发送构帧临时缓冲:每轮申请/释放,避免与其他线程共享同一指针导致并发问题
|
||||||
IntPtr msgPtSend = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CAN.CAN_MSG)));
|
IntPtr msgPtSend = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CAN.CAN_MSG)));
|
||||||
try
|
int Index = 0;
|
||||||
|
//循环给MSG赋值数据
|
||||||
|
foreach (var itemMsg in GroupMsg)
|
||||||
{
|
{
|
||||||
int Index = 0;
|
foreach (var itemSignal in itemMsg)
|
||||||
//循环给MSG赋值数据;DBC 解析器在 .Net 侧不是线程安全的,必须串行化
|
|
||||||
lock (_dbcParserLock)
|
|
||||||
{
|
{
|
||||||
foreach (var itemMsg in GroupMsg)
|
CAN_DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder(itemMsg.Key), new StringBuilder(itemSignal.SignalName), itemSignal.SignalCmdValue);
|
||||||
{
|
|
||||||
foreach (var itemSignal in itemMsg)
|
|
||||||
{
|
|
||||||
CAN_DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder(itemMsg.Key), new StringBuilder(itemSignal.SignalName), itemSignal.SignalCmdValue);
|
|
||||||
}
|
|
||||||
CAN_DBCParser.DBC_SyncValueToCANMsg(DBCHandle, new StringBuilder(itemMsg.Key), msgPtSend);
|
|
||||||
CanMsg[Index] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure(msgPtSend, typeof(USB2CAN.CAN_MSG));
|
|
||||||
Index++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
CAN_DBCParser.DBC_SyncValueToCANMsg(DBCHandle, new StringBuilder(itemMsg.Key), msgPtSend);
|
||||||
|
CanMsg[Index] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure(msgPtSend, typeof(USB2CAN.CAN_MSG));
|
||||||
|
Index++;
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
//通过DBC写入数据后生成CanMsg
|
||||||
// 释放非托管缓冲区(务必释放,否则长时间运行会造成内存泄漏)
|
//将信号值填入CAN消息里面
|
||||||
Marshal.FreeHGlobal(msgPtSend);
|
|
||||||
}
|
// 释放非托管缓冲区(务必释放,否则长时间运行会造成内存泄漏)
|
||||||
|
Marshal.FreeHGlobal(msgPtSend);
|
||||||
|
|
||||||
//发送CAN数据
|
//发送CAN数据
|
||||||
int SendedNum = USB2CAN.CAN_SendMsg(DevHandle, WriteCANIndex, CanMsg, (uint)CanMsg.Length);
|
int SendedNum = USB2CAN.CAN_SendMsg(DevHandle, WriteCANIndex, CanMsg, (uint)CanMsg.Length);
|
||||||
IsSendOk = SendedNum >= 0;
|
if (SendedNum >= 0)
|
||||||
|
{
|
||||||
|
//Console.WriteLine("Success send frames:{0}", SendedNum);
|
||||||
|
IsSendOk = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Console.WriteLine("Send CAN data failed! {0}", SendedNum);
|
||||||
|
IsSendOk = false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
<LegacyCorruptedStateExceptionsPolicy>true</LegacyCorruptedStateExceptionsPolicy>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -214,52 +214,27 @@ namespace CapMachine.Wpf.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void CycleSendMsg()
|
public void CycleSendMsg()
|
||||||
{
|
{
|
||||||
if (!ToomossCanDrive.OpenState)
|
if (ToomossCanDrive.OpenState)
|
||||||
{
|
{
|
||||||
System.Windows.MessageBox.Show("CAN未打开,请先连接CAN", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand);
|
if (ToomossCanDrive.IsCycleSend == false)
|
||||||
return;
|
{
|
||||||
}
|
if (CmdData.Count > 0)
|
||||||
|
|
||||||
//停止已在运行的循环
|
|
||||||
if (ToomossCanDrive.IsCycleSend == true)
|
|
||||||
{
|
|
||||||
ToomossCanDrive.StopCycleSendMsg();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//必要的前置校验:DBC 必须已解析成功,否则原生互操作直接 AccessViolation 闪退
|
|
||||||
if (!ToomossCanDrive.DbcParserState || ToomossCanDrive.DBCHandle == 0)
|
|
||||||
{
|
|
||||||
System.Windows.MessageBox.Show("DBC尚未解析成功,无法循环发送", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//过滤掉 MsgName / SignalName 为空的行(空名传给原生 DBC 解析器是 AV 常见诱因)
|
|
||||||
List<CanCmdData> cmdDataSnapshot;
|
|
||||||
lock (_cmdDataLock)
|
|
||||||
{
|
|
||||||
cmdDataSnapshot = CmdData
|
|
||||||
.Where(x => !string.IsNullOrWhiteSpace(x.MsgName) && !string.IsNullOrWhiteSpace(x.SignalName))
|
|
||||||
.Select(x => new CanCmdData
|
|
||||||
{
|
{
|
||||||
ConfigName = x.ConfigName,
|
ToomossCanDrive.IsCycleSend = true;
|
||||||
MsgName = x.MsgName,
|
ToomossCanDrive.CmdData = CmdData;
|
||||||
SignalName = x.SignalName,
|
ToomossCanDrive.StartPrecisionCycleSendMsg();
|
||||||
SignalCmdValue = x.SignalCmdValue
|
}
|
||||||
})
|
else
|
||||||
.ToList();
|
{
|
||||||
}
|
System.Windows.MessageBox.Show("未发现配置的数据内容", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ToomossCanDrive.StopCycleSendMsg();
|
||||||
|
}
|
||||||
|
|
||||||
if (cmdDataSnapshot.Count == 0)
|
|
||||||
{
|
|
||||||
System.Windows.MessageBox.Show("未发现可发送的数据(请检查写入配置的【消息名称】/【信号名称】是否为空)", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ToomossCanDrive.IsCycleSend = true;
|
|
||||||
//传入的是已经过滤的快照副本,避免与 UI 线程共享同一引用
|
|
||||||
ToomossCanDrive.CmdData = cmdDataSnapshot;
|
|
||||||
ToomossCanDrive.StartPrecisionCycleSendMsg();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user