【发布时间】:2016-09-05 13:48:19
【问题描述】:
首先,简要介绍一下该应用程序。 我们正在开发一种无线传感器,它使用单一特性(硬件限制)通过 BLE 将数据发送到客户端 UWP 应用程序。消息的大小从 20 字节以下到 512 字节不等。消息由起始字符 (start_char)、前导、数据、用于检测错误的 CRC 和结束字符 (end_char) 组成。如果这些特殊字符出现在消息中,它们会被转义。
客户端的消息处理包括以下内容:
- 监听 GattCharacteristic 上的 Characteristic.ValueChanged 事件。
- 将生成的字节数组传递给构建消息的解析器。
- 将生成的消息传递给设备对象进行解释。
如果消息大于 20 字节,BLE 层会自动将其拆分为多个较小的字节数组,每个数组都会触发 Characteristic.ValueChanged 事件。 解析器包含一个 AddBytes(byte[] data) 方法,它在收到 start_char 时开始一条新消息,并存储后续数据,直到收到 end_char,然后计算消息的 CRC 并传递。
当接收到大于 20 字节的消息时会出现此问题,并且看起来有些 20 字节长的数组正在交换。下图显示了一条 512 字节的消息,出于调试目的,该消息被设置为表示三角波(2 次上升)。我已经标出了数据损坏的地方。
起初我认为这是一个线程问题,因为每个 Characteristic.ValueChanged 事件都会在一个单独的线程上触发(我可能对此有误),所以我尝试使用这个:
public class ScheduledBuffer : MessageBuffer
{
#region Fields / Properties
TaskScheduler scheduler;
TaskFactory taskFactory;
#endregion
#region Methods
#region Constructors
public ScheduledBuffer() : base()
{
scheduler = TaskScheduler.FromCurrentSynchronizationContext();
taskFactory = new TaskFactory(scheduler);
}
#endregion
#region Private Methods
void ProcessByteArray(byte[] buffer)
{
foreach (byte b in buffer)
{
ProcessByte(b);
}
}
#endregion
#region Public Methods
public override void AddBytes(byte[] newData)
{
taskFactory
.StartNew(() => { ProcessByteArray(newData); })
.ContinueWith(t => { });
}
#endregion
#endregion
#region Events
#endregion
#region Commands
#endregion
}
目标是将 20 字节长的数组排队等待处理,这样我就不会在前一个数组完成之前开始处理新数组。 ProcessByte(byte b) 是 MessageBuffer 的一种方法,负责转义和添加到新的消息缓冲区。当它获得一个 end_char 时,它通过 MessageReceived 事件将消息传递给潜在的订阅者。
这个实现有什么问题吗,或者 BLE 层是否有可能在给我 ValueChanged 通知之前交换字节数组?这种行为还有哪些其他可能的来源?
附带说明,该应用程序也在为 Android 和 iOS 开发,在这两个平台上都没有这样的问题。
另一件值得一提的是,在功能更强大的机器上运行应用程序时,这些错误的频率会降低,而在我的 Lumia 640 上,我很少收到正确的消息。
【问题讨论】:
-
这是 Windows 中的一个错误。见stackoverflow.com/questions/23848634/…。
标签: c# async-await win-universal-app scheduled-tasks bluetooth-lowenergy