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

蓝牙BLE订阅Adafruit板Notify功能时触发System.ObjectDisposedException异常求助

Troubleshooting System.ObjectDisposedException When Subscribing to Adafruit Board's Notify Feature

Let’s break down your issue and walk through the most likely causes and fixes—this is a common gotcha with BLE in C#, so you’re not alone here.

First, the core of that System.ObjectDisposedException ("The object has been closed") is straightforward: the BLE object you’re trying to interact with (like a GattCharacteristic, GattDescriptor, or even the underlying connection session) has already been disposed of or marked as closed when you attempt to write the Client Characteristic Configuration Descriptor (CCCD) to enable Notify.

Let’s address your specific questions first:

  1. Does the board continuously writing data cause this?
    No, the board actively sending Notify data won’t directly trigger this exception. However, if your code accidentally disposes of BLE objects while handling incoming data (e.g., you call Dispose() on the characteristic in a value-changed callback), that would lead to this error if you try to reconfigure Notify later.

  2. Do I have to write the CCCD before the board starts writing data?
    Not necessarily—but you do need to write the CCCD while the characteristic, service, and BLE connection are still active. If the board is already sending data, that means Notify was already enabled at some point. If you’re seeing this exception when trying to re-enable Notify, it’s likely the underlying objects were released in the meantime.

Most Common Root Causes & Fixes

1. Poor Object Lifecycle Management

C# BLE APIs (like those in Windows.Devices.Bluetooth.GenericAttributeProfile) rely heavily on object references staying alive. If you declare GattCharacteristic or GattDeviceService as local variables (e.g., inside a method that exits quickly), the garbage collector might dispose of them before you can interact with them.

Fix:

  • Declare your BLE objects (characteristic, service, session) as class-level fields instead of local variables. This keeps them in scope for the lifetime of your connection.
  • Avoid calling Dispose() on these objects until you’re completely done with the connection (e.g., when the user explicitly disconnects the device).

2. Out-of-Order Async Operations

BLE operations are asynchronous, and if you try to write the CCCD before the connection is fully established, or before the characteristic is successfully retrieved, you might end up operating on a partially initialized (or already disposed) object.

Fix:

  • Always await asynchronous BLE operations (like GetCharacteristicsAsync() or ConnectAsync()) before proceeding to write the CCCD.
  • Check the connection status (GattDeviceService.ConnectionStatus) before any operation to ensure the device is still connected.

3. Accidental Disposal in Callbacks

It’s easy to accidentally dispose of BLE objects in the ValueChanged callback (where you handle incoming data). For example, if you have cleanup logic that runs when data stops coming in, it might dispose of the characteristic prematurely.

Fix:

  • Never dispose of BLE objects inside the ValueChanged callback. Handle cleanup only when you intentionally disconnect the device.
  • If you need to stop receiving data, disable Notify by writing the "disable" value to the CCCD instead of disposing the characteristic.

4. Unexpected Connection Drops

If the BLE connection drops (e.g., the board goes out of range, loses power) before you write the CCCD, the underlying GattSession will be closed, and any operations on related objects will throw this exception.

Fix:

  • Register for the GattDeviceService.ConnectionStatusChanged event to detect when the connection drops. Pause or retry operations only when the connection is active.
  • Add error handling around the CCCD write operation to catch this exception and trigger a reconnection flow if needed.

Quick Code Example to Avoid the Exception

Here’s a simplified snippet that follows best practices:

// Class-level fields to keep BLE objects alive
private GattCharacteristic _notifyChar;
private GattDeviceService _deviceService;

private async Task EnableNotifySafely()
{
    // Guard clauses to ensure valid state
    if (_deviceService?.ConnectionStatus != GattConnectionStatus.Connected)
    {
        Console.WriteLine("Device not connected—can't enable Notify");
        return;
    }

    if (_notifyChar == null)
    {
        // Re-fetch the characteristic if it's null (e.g., after reconnection)
        var chars = await _deviceService.GetCharacteristicsAsync();
        _notifyChar = chars.Characteristics.FirstOrDefault(c => c.Uuid == YOUR_NOTIFY_CHAR_UUID);
        if (_notifyChar == null)
        {
            Console.WriteLine("Notify characteristic not found");
            return;
        }
    }

    // Get the CCCD descriptor
    var cccd = _notifyChar.GetDescriptors(GattDescriptorUuids.ClientCharacteristicConfiguration).FirstOrDefault();
    if (cccd == null)
    {
        Console.WriteLine("CCCD descriptor missing");
        return;
    }

    try
    {
        // Write to enable Notify
        await cccd.WriteValueAsync(GattCharacteristicNotificationValue.EnableNotification);
        // Register for data updates
        _notifyChar.ValueChanged += OnNotifyDataReceived;
    }
    catch (ObjectDisposedException ex)
    {
        Console.WriteLine($"Failed to enable Notify: {ex.Message}");
        // Trigger reconnection or re-fetch objects here
    }
}

private void OnNotifyDataReceived(GattCharacteristic sender, GattValueChangedEventArgs args)
{
    // Process incoming data—don't dispose of sender here!
    var data = args.CharacteristicValue;
    // Your data handling logic...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:08:43