我的应用程序是在Raspberry Pi3 SBC上运行Win 10 Iot build 10.0.17035.1000的无头UWP。有一段时间我试图在停止命令后解决BLEWatcher Start上的应用程序挂起。为了模拟我的应用程序行为,我将一些代码放在样本MS BluetoothAdvertisement解决方案中,并将其作为Raspberry Pi 3 SBC的独立应用程序运行。大约一个小时后,问题出现了 - 应用程序刚刚挂起。我认为停止当前的BluettothLEDevice BLE特性和处理这个对象可以得到改进。请告诉我,可能是什么问题。这是我的代码:public sealed partial class Scenario1_Watcher:Page
{
// ------------------------------------------------ -------
private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher,
BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
instalinkUUID = "";
bool result = false;
string message = "";
if (watcher.Status == BluetoothLEAdvertisementWatcherStatus.Started)
{
if (oneTime == false)
{
oneTime = true;
watcher.Stop();
rootPage.NotifyUser("BLEWatcher stopped!", NotifyType.StatusMessage);
//
// connect to the detected advertizing device!!!
//
device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress);
message = String.Format("BLE device with ID {0} is connected.", device.DeviceId);
ETWLogging.LogToETWDiagnosticLoggingChannelProvider(message);
}
else
return;
}
// We can obtain various information about the advertisement we just received by accessing
// the properties of the EventArgs class
// The timestamp of the event
DateTimeOffset timestamp = eventArgs.Timestamp;
// The type of advertisement
BluetoothLEAdvertisementType advertisementType = eventArgs.AdvertisementType;
// The received signal strength indicator (RSSI)
Int16 rssi = eventArgs.RawSignalStrengthInDBm;
// The local name of the advertising device contained within the payload, if any
string localName = eventArgs.Advertisement.LocalName;
// Check if there are any manufacturer-specific sections.
// If there is, print the raw data of the first manufacturer section (if there are multiple).
string manufacturerDataString = "";
var manufacturerSections = eventArgs.Advertisement.ManufacturerData;
if (manufacturerSections.Count > 0)
{
// Only print the first one of the list
var manufacturerData = manufacturerSections[0];
var data = new byte[manufacturerData.Data.Length];
using (var reader = DataReader.FromBuffer(manufacturerData.Data))
{
reader.ReadBytes(data);
}
// Print the company ID + the raw data in hex format
manufacturerDataString = string.Format("0x{0}: {1}",
manufacturerData.CompanyId.ToString("X"),
BitConverter.ToString(data));
}
// Serialize UI update to the main UI thread
await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
// Display these information on the list
ReceivedAdvertisementListBox.Items.Add(string.Format("[{0}]: type={1}, rssi={2}, name={3}, manufacturerData=[{4}]",
timestamp.ToString("yyyy MM dd hh\\:mm\\:ss\\.fff"),
advertisementType.ToString(),
rssi.ToString(),
localName,
manufacturerDataString));
});
//
// simulate BLE device service processing
//
await Task.Delay(10000);
//
// disconnect BLE device
//
result = await DisconnectBLEDevice(device);
message = String.Format("BLE device with ID {0} has been disconnected!", device.DeviceId);
ETWLogging.LogToETWDiagnosticLoggingChannelProvider(message);
if (watcher.Status == BluetoothLEAdvertisementWatcherStatus.Stopped)
{
watcher.Start();
rootPage.NotifyUser("Try to start the BLEWatcher.", NotifyType.StatusMessage);
await Task.Delay(1000);
if (watcher.Status == BluetoothLEAdvertisementWatcherStatus.Aborted)
{
rootPage.NotifyUser("BLEWatcher aborted!", NotifyType.StatusMessage);
message = "BLEWatcher aborted!";
ETWLogging.LogToETWDiagnosticLoggingChannelProvider(message);
}
else if(watcher.Status == BluetoothLEAdvertisementWatcherStatus.Started)
{
rootPage.NotifyUser("BLEWatcher (re)started!", NotifyType.StatusMessage);
oneTime = false;
}
else
{
rootPage.NotifyUser("BLEWatcher error!", NotifyType.StatusMessage);
}
}
else if(watcher.Status == BluetoothLEAdvertisementWatcherStatus.Aborted)
{
rootPage.NotifyUser("BLEWatcher aborted!", NotifyType.StatusMessage);
message = "BLEWatcher aborted!";
ETWLogging.LogToETWDiagnosticLoggingChannelProvider(message);
}
}
private async void OnAdvertisementWatcherStopped(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementWatcherStoppedEventArgs eventArgs)
{
string message = "";
// Notify the user that the watcher was stopped
await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
rootPage.NotifyUser(string.Format("Watcher stopped or aborted: {0}", eventArgs.Error.ToString()), NotifyType.StatusMessage);
if (watcher.Status == BluetoothLEAdvertisementWatcherStatus.Aborted)
{
message = String.Format("Watcher aborted: {0}!!!", eventArgs.Error.ToString());
ETWLogging.LogToETWDiagnosticLoggingChannelProvider(message);
rootPage.NotifyUser(message, NotifyType.StatusMessage);
}
});
}
private async Task<bool> DisconnectBLEDevice(BluetoothLEDevice bleDevice)
{
bool result = false;
string message = "";
if (bleDevice == null)
{
message = "DisconnectBLEDevice(): BLE device is null!";
rootPage.NotifyUser(message, NotifyType.StatusMessage);
await Task.Delay(1000);
return result;
}
try
{
result = await DisposeActiveServicesAndCharacteristics(device);
}
catch(Exception ex)
{
message = String.Format("DisconnectBLEDevice(): exception: {0}- FAILED", ex.ToString());
rootPage.NotifyUser(message, NotifyType.StatusMessage);
}
finally
{
bleDevice.Dispose();
bleDevice = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
return result;
}
private async Task<bool> DisposeActiveServicesAndCharacteristics(
BluetoothLEDevice device)
{
bool result = false;
string message = "";
if (device == null)
{
message = string.Format("DisposeActiveServicesAndCharacteristics(): " +
"BLE device with ID {0} is null!", device.DeviceId.ToString());
rootPage.NotifyUser(message, NotifyType.StatusMessage);
return result;
}
if (device.ConnectionStatus == BluetoothConnectionStatus.Disconnected)
{
message = string.Format("DisposeActiveServicesAndCharacteristics(): " +
"BLE device with ID {0} is disconnected!", device.DeviceId.ToString());
rootPage.NotifyUser(message, NotifyType.StatusMessage);
return result;
}
try
{
var services = await device.GetGattServicesAsync();
if ((services == null) || ((services.Services.Count == 0)))
{
message = String.Format("DisposeActiveServicesAndCharacteristics(): GATT Services " +
"for Instadose device with ID {0} are incorrect.",
device.DeviceId.ToString());
rootPage.NotifyUser(message, NotifyType.StatusMessage);
return result;
}
if (services.Status == GattCommunicationStatus.Unreachable)
{
message = String.Format("DisposeActiveServicesAndCharacteristics(): Services " +
"for Instadose device with ID {0} are unreachable.",
device.DeviceId.ToString());
rootPage.NotifyUser(message, NotifyType.StatusMessage);
return result;
}
foreach (var service in services.Services)
{
// check if this service is active
if (service?.Session.SessionStatus == GattSessionStatus.Active)
{
// Not yet implemented in C#
// service?.GattSession.Close();
//service?.Dispose();
}
service?.Session?.Dispose();
service?.Dispose();
}
result = true;
message = String.Format("DisposeActiveServicesAndCharacteristics(): " +
"Instadose device with ID {0} GATT " +
"Services and Charteristics sucessfully disposed- PASSED",
device.DeviceId.ToString());
}
catch (Exception ex)
{
message = ex.ToString();
message = String.Format("DisposeActiveServicesAndCharacteristics(): exception: " +
"{0} for device with ID {1}", message, device.DeviceId.ToString());
rootPage.NotifyUser(message, NotifyType.StatusMessage);
}
return result;
}
}
class ETWLogging
{
static LoggingChannel lc = new LoggingChannel("My provider", null, new Guid("4bd2826e-54a1-4ba9-bf63-92b73ea1ac4a"));
/// <summary>
/// LogToETWDiagnosticLoggingChannelProvider
/// </summary>
public static void LogToETWDiagnosticLoggingChannelProvider(String message)
{
// get ETW trace for Device Portal display
lc.LogMessage(message);
}
}