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

C#开发中ListBox重复显示BLE设备的问题如何修复

问题:BLE设备搜索时ListBox大量显示同名设备

我运行代码点击“搜索”按钮后,程序能检测到附近的BLE设备,但ListBox里总是出现大量同名的设备条目,请问该怎么修复?

相关代码

public Form1() {
    items = new List<string>();
    InitializeComponent();
    txtStatus.Text = "Press 'Search' to begin";
    var watcher = new BluetoothLEAdvertisementWatcher();
    watcher.ScanningMode = BluetoothLEScanningMode.Active;
    watcher.Received += OnAdvertisementReceived;
    watcher.Start();
}
private void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs) {
    items.Add(eventArgs.Advertisement.LocalName);
}

现象说明

ListBox中重复出现多个相同名称的设备条目,同一个物理设备被多次添加到列表中。


解决方案:基于设备唯一标识去重

这问题其实挺常见的——BLE设备会周期性广播广告包,你现在的代码是每次收到广播就往列表里加,自然会出现大量重复。核心解决思路是用每个BLE设备的唯一硬件标识来过滤,而不是只依赖设备名称(毕竟不仅同一设备会多次广播,还可能存在同名的不同设备)。

下面给你两种实用的修复方案:

方案1:用字典存储实现自动去重

每个BLE设备都有独一无二的蓝牙硬件地址(BluetoothAddress),我们可以用Dictionary<ulong, string>来存储,键是蓝牙地址,值是设备名称,字典天然会保证键的唯一性:

// 替换原来的List<string>,用字典存设备地址和对应名称
private Dictionary<ulong, string> deviceDict = new Dictionary<ulong, string>();

public Form1() {
    InitializeComponent();
    txtStatus.Text = "Press 'Search' to begin";
    var watcher = new BluetoothLEAdvertisementWatcher();
    watcher.ScanningMode = BluetoothLEScanningMode.Active;
    watcher.Received += OnAdvertisementReceived;
    watcher.Start();
}

private void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs) {
    // 获取设备唯一蓝牙地址
    ulong deviceAddress = eventArgs.BluetoothAddress;
    // 处理设备名称为空的情况,用地址兜底显示
    string deviceName = string.IsNullOrEmpty(eventArgs.Advertisement.LocalName) 
        ? $"未命名设备 ({deviceAddress:X})" 
        : eventArgs.Advertisement.LocalName;

    // 只添加字典中没有的新设备
    if (!deviceDict.ContainsKey(deviceAddress))
    {
        deviceDict.Add(deviceAddress, deviceName);
        // 注意:UI操作必须回到主线程,否则会触发跨线程异常!
        Invoke((Action)(() => {
            listBoxDevices.Items.Add(deviceName);
        }));
    }
}

方案2:用List配合HashSet做去重判断

如果你更习惯用List来存储设备名称,可以额外维护一个HashSet<ulong>来记录已经扫描过的设备地址,避免重复添加:

private List<string> deviceNames = new List<string>();
// 用HashSet存储已扫描的设备地址,判断效率更高
private HashSet<ulong> scannedAddresses = new HashSet<ulong>();

private void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs) {
    ulong deviceAddress = eventArgs.BluetoothAddress;
    string deviceName = string.IsNullOrEmpty(eventArgs.Advertisement.LocalName) 
        ? $"未命名设备 ({deviceAddress:X})" 
        : eventArgs.Advertisement.LocalName;

    // 检查地址是否已存在,不存在才添加
    if (!scannedAddresses.Contains(deviceAddress))
    {
        scannedAddresses.Add(deviceAddress);
        deviceNames.Add(deviceName);
        // 同样要切回主线程更新UI
        Invoke((Action)(() => {
            listBoxDevices.Items.Add(deviceName);
        }));
    }
}

重要提醒

  • 跨线程UI操作:OnAdvertisementReceived事件是在后台线程触发的,直接操作WinForm的控件会抛出异常,所以一定要用Invoke把UI更新逻辑切回主线程。
  • 空名称处理:有些BLE设备不会在广播中携带设备名称,所以要做兜底处理,避免列表中出现空条目。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:24:21