10 KiB
现场问题分析与修复说明
1. 项目功能理解
当前项目是一个面向车身测量场景的分析软件,核心职责可以拆成 4 个连续步骤:
- 读取现场目录中的 NextSense CSV 文件
- 解析 CSV 内容并写入数据库
- 根据车型和左右侧规则进行分发移动
- 当同一车号左右两侧数据齐全后,生成客户报告
代码中的主要入口与职责如下:
FormMain.FileSortTimer_Tick- 定时触发分发任务
- 文件位置:FormMain.cs
FileSorter.ProcessFiles- 查询启用的分发任务
- 对源目录执行扫描、匹配、移动、解析
- 文件位置:FileSorter.cs
FileSorter.AnalysisNxsCSV- 解析 CSV、写入数据库、触发 UI 更新、判断双侧是否完成
- 文件位置:FileSorter.cs
CjlrDAL.HasBothSidesMeasureResult- 判断同一
CarID是否同时存在L、R两侧结果 - 文件位置:CjlrDAL.cs
- 判断同一
2. 现场分发规则理解
根据现场配置界面,当前数据库中维护了 6 条分发规则:
| 任务名称 | 车型代码 | 位置 | 源路径 | 目标路径 |
|---|---|---|---|---|
L551R_C11 |
L551_21MY |
R |
P:\ |
K:\L551R 21MY |
L551L_C11 |
L551_21MY |
L |
O:\ |
L:\L551L 21MY |
E03L_C11 |
E03 |
L |
O:\ |
L:\E03L |
E03R_C11 |
E03 |
R |
P:\ |
K:\E03R |
E0YL_C11 |
E0Y |
L |
O:\ |
L:\E0YL |
E0YR_C11 |
E0Y |
R |
P:\ |
K:\E0YR |
在代码里,每条规则最终会形成一个匹配特征符:
L551_21MY_RL551_21MY_LE03_RE03_LE0Y_RE0Y_L
旧逻辑的匹配方式是:
- 打开 CSV
- 读取第 3 行第 2 列,也就是
MEASGROUPNAME - 用
Contains判断是否命中目标特征符
旧实现位置:
3. 现场样本数据理解
结合 现场问题/20260520-现场数据 中的样本文件,现场目录中的实际分布如下:
3.1 P 目录
P 目录是右侧来源目录,现场样本中实际包含:
E03_RE0Y_R20250929
示例:
- T2559507.csv
MEASGROUPNAME = E03_R
- T0559698.csv
MEASGROUPNAME = E0Y_R20250929
3.2 O 目录
O 目录是左侧来源目录,现场样本中实际包含:
E03_LE0Y_L20250929
示例:
- TX559018.csv
MEASGROUPNAME = E0Y_L20250929
3.3 L 目录
L 目录样本中主要是:
L551_21MY_L
示例:
- T0554809.csv
MEASGROUPNAME = L551_21MY_L
3.4 K 目录
K 目录样本中主要是:
E03_R
示例:
- T5557787.csv
MEASGROUPNAME = E03_R
4. 升级后现场日志结论
升级后日志文件:
从日志可以确认:
- 程序确实查到了 6 条任务
- 但日志里只完整执行到了第一条规则
L551_21MY_R - 第一条规则对
P:\扫描时,大量文件未命中 - 同时仍然存在“解析入库成功,但该文件不属于当前规则”的情况
关键日志:
- 查询到 6 条任务
- 第一条执行规则
- 第一条规则的目标特征符
- 后续大量
未匹配到文件 - 期间分发定时器因防重入被跳过
5. 问题根因总结
5.1 原逻辑是“按规则扫目录”,不是“按文件路由”
旧逻辑会这样执行:
- 第一条规则扫描整个
P:\ - 第二条规则扫描整个
O:\ - 第三条规则再扫描整个
O:\ - 第四条规则再扫描整个
P:\
这意味着同一个目录会被重复遍历多次。
5.2 旧逻辑是“先解析入库,再做分发匹配”
在旧实现中,每个文件进入循环后会先执行:
AnalysisNxsCSV(file)
然后才判断是否属于当前规则。
这会导致:
- 不属于当前规则的文件也会先入库
- 第一条规则处理时间过长
- 日志里会出现“已导入成功,但未匹配到当前规则”
5.3 旧匹配对 E0Y_R20250929 这类带日期后缀的值不稳定
现场 E0Y 组名带日期后缀:
E0Y_R20250929E0Y_L20250929
如果规则写的是 E0Y_R、E0Y_L,仅依赖简单字符串匹配不够稳,后续维护也容易出问题。
5.4 已处理文件仍参与后续匹配判断,日志噪音大
旧逻辑中,即使文件已经在数据库里标记为已处理,仍可能继续参与分发阶段的匹配判断,导致现场反复看到:
文件已处理过,跳过未匹配到文件
这不利于现场判断真实问题。
5.5 双侧报告逻辑依赖左右两侧 CarID 一致
当前报告逻辑仍然是:
- 同一
CarID - 同时拥有
L、R - 才视为双侧完成
这一规则当前没有修改。现场很多样本左右车号并不完全对齐,所以即使分发成功,也可能仍然无法生成报告。
6. 本次已实施的优化
本次按你的要求,先只落地前 4 点优化,不改“双侧报告匹配规则”。
6.1 优化 1:先匹配分发,再解析入库
已调整为:
- 先读取 CSV 第 3 行第 2 列
- 判断是否命中某条规则
- 命中后先移动到目标目录
- 再对移动后的文件执行
AnalysisNxsCSV
这样可以避免:
- 不属于当前规则的文件被提前入库
- 第一条规则把整盘无关文件都先解析一遍
对应实现位置:
6.2 优化 2:一个源目录只扫描一遍
已把原来“每条规则单独扫目录”的方式,改成:
- 先按
sourceDir对规则分组 - 对每个源目录只扫描一遍
- 每个文件只读取一次特征值
- 再在该目录对应的规则集合中做匹配
这样:
P:\不会被L551R、E03R、E0YR分别重复扫描O:\也不会被多条左侧规则重复扫描
对应实现位置:
6.3 优化 3:已处理文件直接跳过后续匹配与解析
已在目录扫描阶段增加处理:
- 如果
_dal.IsFileProcessed(file)为true - 直接
continue - 不再参与后续匹配
- 不再重复输出“未匹配到文件”
这样能明显减少现场日志噪音。
对应实现位置:
6.4 优化 4:匹配规则标准化
已新增标准化逻辑 NormalizeMatchToken:
E0Y_R20250929标准化为E0Y_RE0Y_L20250929标准化为E0Y_LE03_R保持为E03_RL551_21MY_R保持为L551_21MY_RL551_21MY_L保持为L551_21MY_L
这样做的好处:
- 兼容现场
E0Y组名带日期后缀 - 不改变
L551_21MY这类三段模型编码 - 后续如果日期后缀变化,不需要再改规则
对应实现位置:
7. 本次代码调整点
本次主要修改文件:
新增或调整的核心结构:
TaskRule- 用于承载单条分发规则
rulesBySource- 将同源目录规则合并处理
TryReadMatchToken- 快速读取并标准化匹配特征
NormalizeMatchToken- 规范化
MEASGROUPNAME
- 规范化
MoveMatchedFile- 统一执行文件移动
InsertTaskDetail- 统一写入分发详情
8. 已验证结果
本次修改后,已完成一次本地编译验证:
- 项目:
NXSAnalysis.csproj - 配置:
Debug | x64 - 结果:
0 error
说明:
- 构建成功
- 仅存在原项目自身的 Telerik 程序集版本 warning
- 不影响本次功能代码编译通过
9. 当前仍未调整的部分
按本次要求,以下逻辑暂未改动:
- 双侧报告匹配规则
- 仍按同一
CarID同时存在L、R结果判断
- 仍按同一
MY车型报告跳过规则- 仍保留原有逻辑
SQLHelper的线程安全重构- 当前文档只记录,未在本轮实现
- 解析线程与其他 CSV 定时器之间的更大范围解耦
- 当前只优化了
FileSorter主链路
- 当前只优化了
10. 后续建议
如果继续往下做,建议优先级如下:
- 重构
SQLHelper,彻底去掉静态连接共享 - 复核双侧报告的
CarID配对规则是否符合现场 - 增加“按目录统计命中数/未命中数”的汇总日志
- 增加“模拟分发”模式,现场可先看命中结果再实际移动
11. 总结
这次现场问题的核心,并不是简单的“规则没配好”,而是旧分发流程本身存在几个结构性问题:
- 按规则重复扫描目录
- 先解析再匹配
- 已处理文件仍重复参与匹配
MEASGROUPNAME标准化不足
本次已经先把这些最影响现场效率和可读性的部分落地优化。
报告生成规则暂未改动,后续如果继续处理“双侧配对失败”的问题,需要结合现场车号规则再单独分析。