Files
zhengxuan.zhang 4d5449f186 优化分发规则
2026-05-20 13:36:31 +08:00

10 KiB
Raw Permalink Blame History

现场问题分析与修复说明

1. 项目功能理解

当前项目是一个面向车身测量场景的分析软件,核心职责可以拆成 4 个连续步骤:

  1. 读取现场目录中的 NextSense CSV 文件
  2. 解析 CSV 内容并写入数据库
  3. 根据车型和左右侧规则进行分发移动
  4. 当同一车号左右两侧数据齐全后,生成客户报告

代码中的主要入口与职责如下:

  • FormMain.FileSortTimer_Tick
  • FileSorter.ProcessFiles
    • 查询启用的分发任务
    • 对源目录执行扫描、匹配、移动、解析
    • 文件位置:FileSorter.cs
  • FileSorter.AnalysisNxsCSV
    • 解析 CSV、写入数据库、触发 UI 更新、判断双侧是否完成
    • 文件位置:FileSorter.cs
  • CjlrDAL.HasBothSidesMeasureResult
    • 判断同一 CarID 是否同时存在 LR 两侧结果
    • 文件位置: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_R
  • L551_21MY_L
  • E03_R
  • E03_L
  • E0Y_R
  • E0Y_L

旧逻辑的匹配方式是:

  1. 打开 CSV
  2. 读取第 3 行第 2 列,也就是 MEASGROUPNAME
  3. Contains 判断是否命中目标特征符

旧实现位置:

3. 现场样本数据理解

结合 现场问题/20260520-现场数据 中的样本文件,现场目录中的实际分布如下:

3.1 P 目录

P 目录是右侧来源目录,现场样本中实际包含:

  • E03_R
  • E0Y_R20250929

示例:

3.2 O 目录

O 目录是左侧来源目录,现场样本中实际包含:

  • E03_L
  • E0Y_L20250929

示例:

3.3 L 目录

L 目录样本中主要是:

  • L551_21MY_L

示例:

3.4 K 目录

K 目录样本中主要是:

  • E03_R

示例:

4. 升级后现场日志结论

升级后日志文件:

从日志可以确认:

  1. 程序确实查到了 6 条任务
  2. 但日志里只完整执行到了第一条规则 L551_21MY_R
  3. 第一条规则对 P:\ 扫描时,大量文件未命中
  4. 同时仍然存在“解析入库成功,但该文件不属于当前规则”的情况

关键日志:

5. 问题根因总结

5.1 原逻辑是“按规则扫目录”,不是“按文件路由”

旧逻辑会这样执行:

  1. 第一条规则扫描整个 P:\
  2. 第二条规则扫描整个 O:\
  3. 第三条规则再扫描整个 O:\
  4. 第四条规则再扫描整个 P:\

这意味着同一个目录会被重复遍历多次。

5.2 旧逻辑是“先解析入库,再做分发匹配”

在旧实现中,每个文件进入循环后会先执行:

  • AnalysisNxsCSV(file)

然后才判断是否属于当前规则。

这会导致:

  • 不属于当前规则的文件也会先入库
  • 第一条规则处理时间过长
  • 日志里会出现“已导入成功,但未匹配到当前规则”

5.3 旧匹配对 E0Y_R20250929 这类带日期后缀的值不稳定

现场 E0Y 组名带日期后缀:

  • E0Y_R20250929
  • E0Y_L20250929

如果规则写的是 E0Y_RE0Y_L,仅依赖简单字符串匹配不够稳,后续维护也容易出问题。

5.4 已处理文件仍参与后续匹配判断,日志噪音大

旧逻辑中,即使文件已经在数据库里标记为已处理,仍可能继续参与分发阶段的匹配判断,导致现场反复看到:

  • 文件已处理过,跳过
  • 未匹配到文件

这不利于现场判断真实问题。

5.5 双侧报告逻辑依赖左右两侧 CarID 一致

当前报告逻辑仍然是:

  • 同一 CarID
  • 同时拥有 LR
  • 才视为双侧完成

这一规则当前没有修改。现场很多样本左右车号并不完全对齐,所以即使分发成功,也可能仍然无法生成报告。

6. 本次已实施的优化

本次按你的要求,先只落地前 4 点优化,不改“双侧报告匹配规则”。

6.1 优化 1:先匹配分发,再解析入库

已调整为:

  1. 先读取 CSV 第 3 行第 2 列
  2. 判断是否命中某条规则
  3. 命中后先移动到目标目录
  4. 再对移动后的文件执行 AnalysisNxsCSV

这样可以避免:

  • 不属于当前规则的文件被提前入库
  • 第一条规则把整盘无关文件都先解析一遍

对应实现位置:

6.2 优化 2:一个源目录只扫描一遍

已把原来“每条规则单独扫目录”的方式,改成:

  1. 先按 sourceDir 对规则分组
  2. 对每个源目录只扫描一遍
  3. 每个文件只读取一次特征值
  4. 再在该目录对应的规则集合中做匹配

这样:

  • P:\ 不会被 L551RE03RE0YR 分别重复扫描
  • O:\ 也不会被多条左侧规则重复扫描

对应实现位置:

6.3 优化 3:已处理文件直接跳过后续匹配与解析

已在目录扫描阶段增加处理:

  • 如果 _dal.IsFileProcessed(file)true
  • 直接 continue
  • 不再参与后续匹配
  • 不再重复输出“未匹配到文件”

这样能明显减少现场日志噪音。

对应实现位置:

6.4 优化 4:匹配规则标准化

已新增标准化逻辑 NormalizeMatchToken

  • E0Y_R20250929 标准化为 E0Y_R
  • E0Y_L20250929 标准化为 E0Y_L
  • E03_R 保持为 E03_R
  • L551_21MY_R 保持为 L551_21MY_R
  • L551_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. 当前仍未调整的部分

按本次要求,以下逻辑暂未改动:

  1. 双侧报告匹配规则
    • 仍按同一 CarID 同时存在 LR 结果判断
  2. MY 车型报告跳过规则
    • 仍保留原有逻辑
  3. SQLHelper 的线程安全重构
    • 当前文档只记录,未在本轮实现
  4. 解析线程与其他 CSV 定时器之间的更大范围解耦
    • 当前只优化了 FileSorter 主链路

10. 后续建议

如果继续往下做,建议优先级如下:

  1. 重构 SQLHelper,彻底去掉静态连接共享
  2. 复核双侧报告的 CarID 配对规则是否符合现场
  3. 增加“按目录统计命中数/未命中数”的汇总日志
  4. 增加“模拟分发”模式,现场可先看命中结果再实际移动

11. 总结

这次现场问题的核心,并不是简单的“规则没配好”,而是旧分发流程本身存在几个结构性问题:

  • 按规则重复扫描目录
  • 先解析再匹配
  • 已处理文件仍重复参与匹配
  • MEASGROUPNAME 标准化不足

本次已经先把这些最影响现场效率和可读性的部分落地优化。
报告生成规则暂未改动,后续如果继续处理“双侧配对失败”的问题,需要结合现场车号规则再单独分析。