简体   繁体   中英

How to register event handler safe in c#?

Im am working an bluetooth low energy desktop windows application for a custom bluetooth service. The device sending the data was tested with Android applications. Now I am working on a windows library in C# to receive messages from the device. The service on the Microcontroller is based on the Atmel CSC service. The microcontroller uses the notification service to establish a serial chat between Client and Server.

My application always crashes with exit code -1073740791 (0xc0000409) . This exit code is caused by a stack overrun (STATUS_STACK_BUFFER_OVERRUN (0xc0000409)) . This is related to a /gs exception. The application receives data for several seconds before it crashes (~5-30seconds?).

This issue occurs when I am registering an event handler for the Bluetooth GATT notify service.

characteristic.ValueChanged += CharacteristicValueChangedRequested;

The event handler looks like:

        private void CharacteristicValueChangedRequested(GattCharacteristic sender, GattValueChangedEventArgs args)
    {
        //GattNotifyCharacteristic_sender.ValueChanged -= CharacteristicValueChangedRequested_Async;
        if (args.CharacteristicValue != null)
        {
            var length = args.CharacteristicValue.Length;
            if (length > 0)
            {
                if (length < 120)
                {
                    var reader = DataReader.FromBuffer(args.CharacteristicValue);
                    LatestClientMessage = reader.ReadString(length);
                    ClientMessages.Add(LatestClientMessage);
                }
            }
        }
        //GattNotifyCharacteristic_sender.ValueChanged += CharacteristicValueChangedRequested_Async;
    }

If I do not register the event handler for received messages the application is stable. If I register an empty event handler with no code the application also crashes with the same exit code. I'll try to receive about 100 notifications per second. The application is a bit more stable if I ll try to receive fewer data.

I ll tried different methods to register an event handler, but I think somehow I need to manage the same event handler being called multiple times.

I also tried to unregister the event handler immediately when called and reregister when finished, but that does not help a lot.

The characteristic is of type GattCharacteristic

GattCharacteristic
using Windows.Devices.Bluetooth.GenericAttributeProfile;

The registration for the notify service is done by the following code:

        /// <summary>
    /// Register for Notification at BLE Device
    /// </summary>
    /// <param name="address"></param>
    /// <param name="Msg"></param>
    public async Task<string> RegisterNotificationForced_Async(ulong address)
    {
        var device = await BluetoothLEDevice.FromBluetoothAddressAsync(address);
        var mGattDeviceServicesResult = await device.GetGattServicesAsync();
        GattCommunicationStatus result = GattCommunicationStatus.Unreachable;

        foreach (var service in mGattDeviceServicesResult.Services)
        {
            if (service.Uuid == mGuid) //Atmel CSC Service
            {
                var mGattCharacteristicsResult = await service.GetCharacteristicsAsync(); //Characteristic on BLE Device
                if (mGattCharacteristicsResult.Status == GattCommunicationStatus.Success)
                {
                    var characteristics = mGattCharacteristicsResult.Characteristics;
                    foreach (var characteristic in characteristics)
                    {
                        if (characteristic.CharacteristicProperties.HasFlag(GattCharacteristicProperties.Notify))
                        {
                            characteristic.ValueChanged += CharacteristicValueChangedRequested;

                            GattClientCharacteristicConfigurationDescriptorValue DescriptorVal;
                            DescriptorVal = GattClientCharacteristicConfigurationDescriptorValue.Notify;
                            result = await characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(DescriptorVal);
                            if (result != GattCommunicationStatus.Success)
                            {
                                throw new System.ArgumentException("Failed to register notification at BLE Device");
                            }
                        }
                    }
                }
                else
                {
                    throw new System.ArgumentException("Characteristics on BLE device not found");
                }
            }
        }
        return $"{result}";
    }

The problem might be related to the windows bluetooth driver and the event handler registered there....

Thank you for your comments...

I was not able to really find the issue related to the problem. The problem does not exist when using the nuget package microsoft.netcore.universalwindowsplatform. At least I found a workaround. Before I was using Microsoft.Windows.SDK Contracts. The new code is based on the following example:

https://docs.microsoft.com/en-us/samples/microsoft/windows-universal-samples/bluetoothle/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM