项目学习代码

当然有!你提供的这段 C# WinForms 代码功能非常完整且考虑周全,尤其是在 UI 交互、多线程处理和状态管理方面做得相当不错。

在此基础上,我们可以从性能、架构和代码可维护性三个角度进行优化,让这个应用变得更加出色。

核心性能优化(高优先级)

这两点改进能最显著地提升应用的流畅度和响应速度。

  1. 数据采集:从"轮询"改为"事件驱动"

    问题:

    你现在的后台任务 RefreshDataLoopAsync 是一个轮询循环,它以固定的 50ms 间隔主动去 GetDeviceData。这种方式的主要缺点是:

    ● 不精确:如果设备回报率高于 20Hz (50ms),你会丢失数据点。如果低于 20Hz,则会进行不必要的空查询,浪费 CPU 资源。

    ● 非实时:数据从产生到被你读取,最多有 50ms 的延迟。

    改进方案:

    利用 SDK 提供的 BWT901BLE_OnRecord 事件。这个事件在传感器主动上报数据时触发,是最理想的数据来源。

    你可以构建一个经典的"生产者-消费者"模型:

  2. 生产者 (OnRecord 事件):在事件回调中,将传感器数据放入一个线程安全的队列(如 System.Collections.Concurrent.BlockingCollection)。

  3. 消费者 (后台任务):后台任务不再使用 Task.Delay,而是持续从队列中取出数据,然后存入你的 _accelerationBuffer 环形缓冲。

    这样做的好处:

    ● 不错过任何数据:只要数据上报,就能被捕获。

    ● 效率极高:没有数据时,后台任务处于等待状态,不消耗 CPU。

    ● 实时性最佳:数据一到就被处理。

  4. 图表绘制:用"滑动窗口"代替"完全重绘"

    问题:

    UpdateChartData 方法每次都调用 Points.Clear() 来清空所有数据点,然后重新添加。即使只显示 100 个点,这种操作也会导致图表闪烁,并且在数据更新频繁时消耗大量资源。

    改进方案:

    实现一个"滑动窗口"式的更新。

  5. 向图表系列(Series)中添加新数据点。

  6. 检查当前点的数量是否超过 MaxDataPoints。

  7. 如果超过,就移除最老的一个数据点 (Points.RemoveAt(0))。

    这样,图表每次只进行最小化的重绘,动画效果会非常平滑流畅。

    C#

    // 示例:滑动更新图表

    private void AddDataPointToChart(AccelerationData data)

    {

    // ...

    var seriesX = chart1.Series["AccX"];

    seriesX.Points.AddXY(data.Timestamp.ToOADate(), data.AccX);

    // 如果点数超过上限,移除最旧的点

    if (seriesX.Points.Count > MaxDataPoints)

    {

    seriesX.Points.RemoveAt(0);

    }

    // ... 对 AccY 和 AccZ 执行相同操作

    // 相应地调整X轴的视图范围

    chart1.ChartAreas[0].AxisX.Minimum = seriesX.Points[0].XValue;

    chart1.ChartAreas[0].AxisX.Maximum = data.Timestamp.ToOADate();

    }

    软件架构优化(提升可维护性)

  8. 类的职责分离(Refactoring)

    问题:

    Form2 这个类承担了太多的责任,它既是 UI 界面,又是蓝牙管理器,还是数据处理器和图表控制器。这使得这个文件非常庞大(超过1500行),难以维护和扩展。

    改进方案:

    将不同的功能模块拆分到独立的类中,遵循"单一职责原则"。

    ● DeviceService.cs: 专门负责蓝牙设备的扫描、连接、数据接收和指令发送。Form 通过调用它来管理设备,并通过事件来接收数据。

    ● ChartController.cs: 专门负责 chart1 的所有操作,如图表初始化、数据更新、样式设置等。

    ● DataRepository.cs: 专门负责 _accelerationBuffer 的管理,如数据存入、读取、清空、导出等。

    这样做的好处:

    ● 代码清晰:Form2.cs 会变得非常简洁,主要负责响应用户操作,并将任务委托给其他类。

    ● 易于维护:修改蓝牙逻辑时,你只需要看 DeviceService.cs 文件。

    ● 可复用和测试:这些独立的业务类可以在其他项目中复用,并且可以单独进行单元测试。

    功能与体验优化(锦上添花)

  9. 支持多设备连接与切换

    问题:

    当前应用在找到第一个符合条件的设备后就停止扫描并进行连接。如果周围有多个传感器,用户无法选择。

    改进方案:

    ● 在 UI 上添加一个 ListBox 或 ComboBox。

    ● 扫描时,将所有找到的设备都添加到这个列表中。

    ● 允许用户从列表中选择一个或多个设备进行连接。

    ● 如果连接了多个设备,可以提供一个下拉框让用户切换图表所显示的数据源。

  10. 耗时操作异步化

    问题:

    exportButton_Click 中的数据导出是同步执行的。如果历史数据非常多,写入文件时会造成 UI 线程阻塞,导致程序"未响应"。

    改进方案:

    将文件写入的核心逻辑放到 Task.Run 中执行,并使用 async/await 来等待它完成,避免冻结界面。

    C#

    private async void exportButton_Click(object sender, EventArgs e)

    {

    // ... 获取文件路径等 ...

    try

    {

    exportButton.Enabled = false; // 禁用按钮,防止重复点击

    ShowStatusMessage("正在导出...", MessageType.Info);

    复制代码
     await Task.Run(() => 
     {
         // 将耗时的文件写入操作放在这里
         File.WriteAllLines(filePath, dataLines); 
     });
    
     ShowStatusMessage("导出成功!", MessageType.Success);

    }

    catch (Exception ex)

    {

    ShowErrorMessage("导出失败", ex);

    }

    finally

    {

    exportButton.Enabled = true; // 恢复按钮

    }

    }

    总结

    总的来说,你的代码基础非常好。如果你希望它能更上一层楼,我强烈建议你:

  11. 首要任务:将数据采集方式从轮询改为事件驱动,并优化图表的更新逻辑。这两项改动对性能的提升是立竿见影的。

  12. 长期考虑:进行代码重构,将功能拆分到不同的类中。这会让你的项目在未来更容易维护和添加新功能。

    希望这些建议对你有所帮助!

相关推荐
&&Citrus10 小时前
【CPN学习笔记(二)】Chap2 非分层颜色 Petri 网——从一个简单协议开始读懂 CPN
笔记·学习·php·cpn·petri网
小橘子83112 小时前
(学习)Claude Code 源码架构深度解析
学习·程序人生·架构
diablobaal14 小时前
云计算学习100天-第102天-Azure入门4
学习·云计算·azure
AI_零食14 小时前
Flutter 框架跨平台鸿蒙开发 - 自定义式按钮设计应用
学习·flutter·ui·华为·harmonyos·鸿蒙
小陈phd14 小时前
多模态大模型学习笔记(三十)—— 基于YOLO26 Pose实现车牌检测
笔记·学习
野指针YZZ14 小时前
XV6操作系统:trap机制学习笔记
笔记·学习
diygwcom15 小时前
学习开源数据采集与监视控制SCADA-即工业组态开源框架FUXA
学习·开源
zl_dfq15 小时前
Python学习5 之【字符串】
python·学习
ada0_ada117 小时前
qt模块学习记录
开发语言·qt·学习