How to stop a call resulting in IAsyncOperation?

1k Views Asked by At

In my application I notify multiple devices. If a device is not reachable and is not responding within a few seconds, i want to cancel the call.

My code is:
await characteristic0.WriteClientCharacteristicConfigurationDescriptorAsync (GattClientCharacteristicConfigurationDescriptorValue.Notify);

Now after some research i found out that usually one can pass a CancelationToken (_ct) and do this:

First create an operation containing the call:
IAsyncOperation<GattCommunicationStatus> operation = characteristic0.WriteClientCharacteristicConfigurationDescriptorAsync (GattClientCharacteristicConfigurationDescriptorValue.Notify);

Then creating a task with a CancellationToken:
Task<GattCommunicationStatus> task = operation.AsTask(_ct);

And then await it:
GattCommunicationStatus status = await task;

Now, the thing is even though the IsCancellationRequested-Property of the CancellationToken is set to true. The call wont stop.
And, the Device is getting Notified after the first line already! Isn't that supposed to happen after the call to await??

Do i make a mistake with the Token or is this a bigger thing?

EDIT
After the conversation with @Andrii Litvinov i put some more code to my initial description of the problem. Here is the whole method:

public async Task<GattCommunicationStatus> NotifyDevice(DeviceInformationDisplay deviceInfo, CancellationToken _ct)
        {
            try
            {
                BluetoothLEDevice device = await BluetoothLEDevice.FromIdAsync(deviceInfo.Id);
                service = device.GetGattService(new Guid(Service_UUID));
                characteristic0 = service.GetCharacteristics(new Guid(Characteristic_0_UUID)).First();

                characteristic0.ValueChanged += characteristic0ValueChanged;
                GattCommunicationStatus status = await characteristic0.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);
                _ct.Register(() =>
                {
                // trying to cancel the operation somehow
                });
                IAsyncOperation<GattCommunicationStatus> operation = characteristic0.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);
                Task<GattCommunicationStatus> task = operation.AsTask(_ct);
                GattCommunicationStatus status_1 = await task;

                if (!elapsedTimeWatcher.IsRunning)
                {
                    elapsedTimeWatcher.Start();
                }

                else
                {
                    elapsedTimeWatcher.Restart();
                }
                return status;
            }
            catch(OperationCanceledException e)
            {
                return GattCommunicationStatus.Unreachable;
            }
            catch (Exception e)
            {
                return GattCommunicationStatus.Unreachable;
            }

        }
1

There are 1 best solutions below

4
On BEST ANSWER

Based on the docs you are doing it right:

try
{
...

IAsyncOperation<GattCommunicationStatus> operation =
    characteristic0.WriteClientCharacteristicConfigurationDescriptorAsync(
        GattClientCharacteristicConfigurationDescriptorValue.Notify);
return await operation.AsTask(_ct);

...
}
...

This code should register to token and call operation.Cancel() behind the scene.

Can you set a token to lower value to see if operation is actually cancelled? How much time does it normally take to execute the method?

Try:

CancellationTokenSource cts = new CancellationTokenSource(10);
await NotifyDevice(BLEDevice, cts.Token);

Or even lower values.