You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#/.NET MAUI中如何将匿名事件处理器重构为可注销委托

.NET MAUI接入Plugin.BLE扫描设备重复条目问题解决方案

你遇到的扫描结果条目随按钮点击次数递增的问题,根因就是每次触发扫描逻辑时,都给全局复用的同一个adapter实例重复绑定了DeviceDiscovered事件处理函数。同一个设备被发现时,所有历史绑定过的处理逻辑会依次执行,自然会出现重复条目,和你测试用的Pixel 5模拟器本身没有直接关系。

具名事件处理函数实现方法

你不需要纠结事件自带的两个参数,这是C#事件的标准签名约定:

  • 第一个参数通常命名为sender,是触发当前事件的源对象实例,这里就是对应的蓝牙适配器,绝大多数场景下用不到,保留参数声明即可
  • 第二个参数通常命名为e,是事件携带的业务参数,这里包含扫描到的蓝牙设备信息,和你之前Lambda表达式里的a用法完全一致

具体实现步骤

  1. 在你的MVVM ViewModel类中,编写独立的具名事件处理方法,和按钮命令方法放在同级:
// 蓝牙设备发现事件处理函数
private void OnBleDeviceDiscovered(object sender, DeviceEventArgs e)
{
    if (!string.IsNullOrEmpty(e.Device.Name))
    {
        // 这里替换为你原来Lambda内部写的业务逻辑
        // 比如将有效设备加入绑定到UI的扫描结果集合,更新UI记得切换到主线程
    }
}

如果你使用的Plugin.BLE版本编译提示参数类型不匹配,把第二个参数的DeviceEventArgs替换为DeviceDiscoveredEventArgs即可,内部e.Device的用法完全不变。

  1. 修改扫描启动逻辑,绑定事件前先做一次兜底注销,避免历史绑定残留:
// 按钮触发扫描时执行的逻辑
// 先兜底注销,就算之前没有绑定过事件,执行这句也不会抛异常
adapter.DeviceDiscovered -= OnBleDeviceDiscovered;
// 绑定具名事件处理函数
adapter.DeviceDiscovered += OnBleDeviceDiscovered;
// 启动扫描
await adapter.StartScanningForDevicesAsync();
  1. 在所有扫描终止的分支(定时器超时、用户手动点击停止)的公共停止逻辑中,执行完停止扫描操作后主动注销事件:
// 停止扫描公共逻辑,所有终止扫描的场景都调用这段代码
await adapter.StopScanningForDevicesAsync();
// 注销事件处理函数,避免后续扫描触发重复逻辑
adapter.DeviceDiscovered -= OnBleDeviceDiscovered;

额外优化建议

安卓模拟器的蓝牙栈本身存在模拟缺陷,就算事件没有重复绑定,也可能出现同一个设备多次上报广播的情况,你可以在添加设备到结果集合时,以设备的唯一标识e.Device.Id(即MAC地址)做去重判断,从业务层彻底避免重复条目问题。

内容的提问来源于stack exchange,提问作者gfmoore

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 04:27:24