CAN优化

This commit is contained in:
2026-07-15 15:47:42 +08:00
parent aebbd88e23
commit 8e44be4894
10 changed files with 117 additions and 30 deletions
+62 -10
View File
@@ -1,4 +1,5 @@
using Common.Attributes;
using Logger;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -29,6 +30,10 @@ namespace ZLGUSBCANFD
// DBC 循环发送任务管理:Key = (通道号, 帧ID)
private readonly ConcurrentDictionary<(uint 通道号, uint 帧ID), CancellationTokenSource> _cyclicSenders = new ConcurrentDictionary<(uint, uint), CancellationTokenSource>();
// 信号值持久化覆盖表:Key = (通道号, 帧ID),Value = 信号名 → 物理值
// 每次 设置报文 会累积写入此表,发送时以 DBC 初始值为底再叠加此表覆盖值
private readonly ConcurrentDictionary<(uint 通道号, uint 帧ID), Dictionary<string, double>> _signalOverrides = new ConcurrentDictionary<(uint, uint), Dictionary<string, double>>();
// 动态硬件参数
private readonly uint _deviceType; // 76: USBCANFD-400U
private readonly uint _deviceIndex; // 设备索引
@@ -371,14 +376,17 @@ namespace ZLGUSBCANFD
}
catch (Exception ex)
{
// 循环发送出错时退出,避免刷屏
Console.WriteLine($"[ZLGCANFD] 循环发送 DBC 报文失败: {ex.Message}");
Logger.LoggerHelper.Error($"[ZLGCANFD] 循环发送 DBC 报文失败: {ex.Message}");
break;
}
}
_cyclicSenders.TryRemove((通道号, 帧ID), out var removedCts);
removedCts?.Dispose();
// 清理:仅当字典中存的仍然是本任务创建的 CTS 时才移除,避免误删新任务的 CTS
if (_cyclicSenders.TryGetValue((通道号, 帧ID), out var current) && ReferenceEquals(current, cts))
{
_cyclicSenders.TryRemove((通道号, 帧ID), out _);
}
cts.Dispose();
}, cts.Token);
return true;
@@ -392,7 +400,7 @@ namespace ZLGUSBCANFD
if (_cyclicSenders.TryRemove((通道号, 帧ID), out var cts))
{
cts.Cancel();
cts.Dispose();
// 不在这里 Dispose,由 Task 的清理代码负责释放,避免 Task 仍在使用已释放的 Token
}
}
@@ -409,6 +417,31 @@ namespace ZLGUSBCANFD
_cyclicSenders.Clear();
}
/// <summary>
/// 清除指定通道、指定帧 ID 的信号覆盖值,恢复为 DBC 初始值。
/// </summary>
public virtual void 清除信号覆盖(uint 通道号, uint 帧ID)
{
if (_signalOverrides.TryRemove((通道号, 帧ID), out var dict))
{
lock (dict) dict.Clear();
}
}
/// <summary>
/// 清除指定通道所有帧的信号覆盖值。
/// </summary>
public virtual void 清除通道信号覆盖(uint 通道号)
{
foreach (var key in _signalOverrides.Keys)
{
if (key.通道号 == 通道号 && _signalOverrides.TryRemove(key, out var dict))
{
lock (dict) dict.Clear();
}
}
}
/// <summary>
@@ -536,7 +569,7 @@ namespace ZLGUSBCANFD
/// <param name="物理值">要写入的实际物理数值</param>
/// <param name="循环发送间隔毫秒">0 = 单次发送;>0 = 周期循环发送(单位毫秒)</param>
/// <returns>操作是否成功</returns>
public virtual bool 设置报文(uint 通道号, string 帧IDStr, string 信号名称, double 物理值, int 循环发送间隔毫秒 = 0)
public virtual bool 设置报文(uint 通道号, string 帧IDStr, string 信号名称, double 物理值, int 循环发送间隔毫秒 = 0, bool 直接发送=false)
{
if (!TryParseFrameId(帧IDStr, out uint 帧ID))
{
@@ -548,12 +581,18 @@ namespace ZLGUSBCANFD
if (!_isDbcLoadedArray[通道号]) return false;
if (string.IsNullOrWhiteSpace(信号名称)) return false;
var merged = 构建报文发送字典(通道号, 帧ID, new Dictionary<string, double>(StringComparer.OrdinalIgnoreCase)
// 将本次设置的信号值写入持久化覆盖表(累积,不会丢失之前设置的值)
var overrides = _signalOverrides.GetOrAdd((通道号, 帧ID), _ => new Dictionary<string, double>(StringComparer.OrdinalIgnoreCase));
lock (overrides)
{
{ 信号名称, 物理值 }
});
overrides[信号名称] = 物理值;
}
return 发送DBC定义报文(通道号, 帧ID, merged, 循环发送间隔毫秒);
// 构建发送字典:DBC 初始值 + 持久化覆盖表(已包含本次设置)
var merged = 构建报文发送字典(通道号, 帧ID);
if (直接发送) return 发送DBC定义报文(通道号, 帧ID, merged, 循环发送间隔毫秒);
else return true;
}
/// <summary>
@@ -753,6 +792,7 @@ namespace ZLGUSBCANFD
var msg = (ZDBC.DBCMessage)Marshal.PtrToStructure(ptrDbcMsg, typeof(ZDBC.DBCMessage));
var dict = new Dictionary<string, double>(StringComparer.OrdinalIgnoreCase);
// 1. DBC 初始值打底
for (int i = 0; i < msg.nSignalCount; i++)
{
var signal = msg.vSignals[i];
@@ -763,6 +803,17 @@ namespace ZLGUSBCANFD
}
}
// 2. 叠加持久化覆盖表(之前 设置报文 累积的值)
if (_signalOverrides.TryGetValue((通道号, 帧ID), out var persisted))
{
lock (persisted)
{
foreach (var kvp in persisted)
dict[kvp.Key] = kvp.Value;
}
}
// 3. 叠加本次调用传入的额外覆盖(优先级最高)
if (额外覆盖 != null)
{
foreach (var kvp in 额外覆盖)
@@ -776,6 +827,7 @@ namespace ZLGUSBCANFD
}
finally
{
Marshal.FreeHGlobal(ptrDbcMsg);
}
}
+1
View File
@@ -8,6 +8,7 @@
<ItemGroup>
<ProjectReference Include="..\Common\Common.csproj" />
<ProjectReference Include="..\Logger\Logger.csproj" />
</ItemGroup>
</Project>