public async Task RemoveDesiredPropertyUpdateCallbackAsync()

in DeviceBridge/Services/ConnectionManager.cs [572:606]


        public async Task RemoveDesiredPropertyUpdateCallbackAsync(string deviceId)
        {
            _logger.Info("Attempting remove desired property change handler for device {deviceId}", deviceId);

            // We need to synchronize this with client creation/close so a race condition doesn't cause us to add the
            // callback to a client that is being currently created but not yet in the clients list.
            var mutex = _clientSemaphores.GetOrAdd(deviceId, new SemaphoreSlim(1, 1));
            await mutex.WaitAsync();

            try
            {
                _logger.Info("Acquired connection lock for device {deviceId}", deviceId);

                // Remove the callback so it's not registered in new clients
                if (_desiredPropertyUpdateCallbacks.TryRemove(deviceId, out _))
                {
                    if (!_clients.TryGetValue(deviceId, out DeviceClient client))
                    {
                        _logger.Info("Connection for device {deviceId} not found while trying to remove desired property change callback", deviceId);
                        return;
                    }

                    // The device SDK does not accept removing a property change callback (or passing null), so we just register an empty one.
                    await client.SetDesiredPropertyUpdateCallbackAsync((_, __) => Task.CompletedTask, null);
                }
                else
                {
                    _logger.Info("Tried to remove desired property change handler for device {deviceId}, but a handler was not registered", deviceId);
                }
            }
            finally
            {
                mutex.Release();
            }
        }