如何解决如何在设备断开连接时取消 BLE 任务?
我正在以 Xamarin 形式进行 BLE 实现。我想在设备断开连接时停止 BLE 任务。我使用取消令牌来停止任务,并调用了一个 void 方法,该方法具有返回值,如以下代码所示:
private async Task ConnectForDevice(ScanData scanData,CancellationTokenSource token)
{
try
{
await _adapter.ConnectToDeviceAsync(_device);
}
catch (DeviceConnectionException ex)
{
await UserDialogs.Instance.AlertAsync("Device got disconnected please scan again 2");
disconnected();
token.Cancel();
}
}
public async void disconnected()
{
await Application.Current.MainPage.Navigation.PopAsync();
return;
}
token.Cancel()
应该停止任务,但不会停止执行。相反,它会执行其他异步任务。有没有办法轻松停止这些异步任务?有什么建议吗?
解决方法
您使用的取消令牌错误,您的代码没有多大意义。
首先,如果这是您要取消的任务,您应该在 CancellationToken
中使用 CancellationTokenSource
而不是 ConnectForDevice
作为参数。您在调用 CancellationTokenSource
的类中创建一个 ConnectForDevices
,将取消源的令牌传递给它,从而能够通过调用 cancellationTaskSource.Cancel()
从调用方取消任务。
我不知道您正在使用的 API/Library,但我认为 * _adapter.ConnectToDeviceAsync
获得 CancellationToken
会导致过载。您传递给您 cancellationToken
,取消后将取消执行。
这将引发 TaskCancelledException
类型的异常(如果在 _adapter.ConnectToDevice
中实现)。我说如果实现,因为调用 cancellationTokenSource.Cancel()
只会标记要取消的令牌,设置 IsCancellationRequested=true
但某处(通常在要取消的方法内)需要调用 token. ThrowIfCancellationRequested()
或手动检查IsCancellationRequested
的状态并抛出或取消或其他任何东西,以停止执行。
此外,我认为 ConnectToDeviceAsync
方法只会连接到设备并在之后返回或抛出异常。这样您将不会收到断开连接的信号。我还认为 DeviceConnectionException
只有在连接到设备时发生异常时才会引发,但这并不意味着断开连接,因为没有连接。
通常会有一个事件通知你这件事,但也可能没有,所以唯一的方法是轮询连接或某事。
所以你的代码变得更像这样:
private async Task ConnectForDevice(ScanData scanData,CancellationToken token)
{
try
{
await _adapter.ConnectToDeviceAsync(_device,token);
}
catch (DeviceConnectionException ex)
{
await UserDialogs.Instance.AlertAsync("Device got disconnected please scan again 2");
}
catch (TaskCanceledException tce)
{
Console.WriteLine("Scan was cancelled");
}
finally
{
await Disconnect();
}
}
public Task Disconnect() //NEVER USE ASYNC VOID,ONLY IN EVENT HANDLERS
{
return Application.Current.MainPage.Navigation.PopAsync();
}
更新
您对 Plugin.BLE 的理解有误。 这是一个基本示例(未用于生产,用于演示)
void Main()
{
//Create your token source
var tcs = new CancellationTokenSource();
//Since we dont await execution goes on to demo cancellation
ScanAndConnectToKnownDevice(/*{yourDeviceId}*/,tcs.Token);
Thread.Sleep(2000)
tcs.Cancel(); //We cancel the process after 2 seconds.
}
async Task ScanAndConnectToKnownDevice(Guid deviceId,CancellationToken cancellationToken)
{
IDevice device;
//CrossBluetoothLE.Current.Adapter has a few events to handle connection changes
//We wire some of them here
//There is an event for when a device disconnects,which
//will be raised when ANY device disconnects
CrossBluetoothLE.Current.Adapter.DeviceDisconnected += OnDeviceDisconnected;
//There is an event for when a device is discovered in scan
CrossBluetoothLE.Current.Adapter.DeviceDiscovered += OnDeviceDiscovered;
//Start scanning process
try
{
await CrossBluetoothLE.Current.Adapter.StartScanningForDevicesAsync(tcs.Token);
}
catch (TaskCanceledException tce)
{
await UserDialogs.Instance.AlertAsync("Scanning was cancelled");
}
catch (Exception ex)
{
await UserDialogs.Instance.AlertAsync("Error scanning for devices");
}
if (device is null)
{
await UserDialogs.Instance.AlertAsync("Device not found!");
}
else
{
try
{
//This will ONLY CONNECT to the device and then RETURN after connection
//The token you are passing here will cancel THE CONNECTION PROCESS,//that does not mean device was disconnected,but that there were problems
//CONNECTING to the device
await BluetoothService.ConnectForDevice(device,tcs.Token);
}
catch (DeviceConnectionException ex)
{
await UserDialogs.Instance.AlertAsync("Error connecting to the device!");
}
catch (TaskCanceledException tce)
{
await UserDialogs.Instance.AlertAsync("Connection process was cancelled!");
}
}
}
private async void OnDeviceDisconnected(object sender,DeviceEventArgs e) //Is OK to use async void here
{
if (a.Device.ID == deviceId)
await UserDialogs.Instance.AlertAsync("Device got disconnected please scan again 2");
}
private void OnDeviceDiscovered(object sender,DeviceEventArgs e) //Is OK to use async void here
{
if (a.Device.ID == deviceId)
_device = a.Device;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。