UWP串行设备数据读取器异常:0x800710DD.操作标识符无效



我正在将功能从一个示例Windows窗体应用程序移植到Xamarin.Forms UWP应用程序,它应该在其中写入&从COM端口上的蓝牙设备读取。我让它大部分时间都能正常工作,但UWP应用程序会间歇性地进入一种状态,任何对dataReader.LoadAsync的调用都会触发异常:

Exception thrown at 0x74AF1A62 (KernelBase.dll) in MyApp.UWP.exe: WinRT originate error - 0x800710DD : 'The operation identifier is not valid.'.
Exception thrown: 'System.Runtime.InteropServices.COMException' in MyApp.UWP.exe
WinRT information: The operation identifier is not valid.

重新启动应用程序或Visual Studio没有帮助,问题仍然存在。

上次发生这种情况时,似乎没有影响我的dataWriter对设备的写入,只是影响了随后的读取。

所有代码都在UWP项目中。

private DataReader _dataReader;
private DataWriter _dataWriter;
private SerialDevice _currentSerialDevice;
private async Task ReadAsync(SerialDevice serialDevice)
{
const uint ReadBufferLength = 1024;
if (_dataReader == null)
{                
_dataReader = new DataReader(_currentSerialDevice.InputStream) { InputStreamOptions = InputStreamOptions.Partial };
}
uint bytesRead = await _dataReader.LoadAsync(ReadBufferLength); // <- exception here
if (bytesRead > 0)
{
var vals = new byte[bytesRead];
_dataReader.ReadBytes(vals);
DoStuffWithBytes(vals);
}
}

串行设备是从应用程序中的列表中选择的。

// Get serial devices
DeviceInformationCollection serialDeviceCollection = await DeviceInformation.FindAllAsync(SerialDevice.GetDeviceSelector());
// Load serial device from user choosing a device from serialDeviceCollection 
public async void ConnectToSerialDevice(DeviceInformation device)
{
_currentSerialDevice = await SerialDevice.FromIdAsync(device.Id);
_currentSerialDevice.BaudRate = 115200;
_currentSerialDevice.Parity = SerialParity.None;
_currentSerialDevice.DataBits = 8;
_currentSerialDevice.StopBits = SerialStopBitCount.One;
_currentSerialDevice.Handshake = SerialHandshake.RequestToSend;
}

写入设备的代码,即使处于奇数状态也能工作:

private async Task WriteToDevice(byte[] outBuffer)
{
if (_currentSerialDevice != null)
{
if (_dataWriter == null)
{
_dataWriter = new DataWriter(_currentSerialDevice.OutputStream);
}
_dataWriter.WriteBytes(outBuffer);
await _dataWriter.StoreAsync();
}
}

我尝试过刷新数据写入程序、重新创建数据写入程序&每次都是数据读取器,但我仍然会收到同样的错误,无法从设备中读取任何内容。在正常操作中,我能够成功读取我期望的字节(即使没有要读取的字节,它也会"读取"0个字节(,并且可以毫无例外地输出这个结果。

令人好奇的是,即使在原始的Windows Forms应用程序处于这种状态后,它不仅能正常工作(使用相同的蓝牙设备(,而且只需打开端口并从设备中读取(在旧应用程序中(,就可以在一段时间内修复UWP应用程序中的问题,让我可以再次从设备中进行读取。

这可能与异步方法有关。你可以试试这个:

var task = await _dataReader.LoadAsync(ReadBufferLength);
task.AsTask().Wait();
uint bytesRead = task.GetResults();

对于异步方法(如DataReader.LoadAsync(,事件发生在UI线程上,并且只能触发一次,并且只有在上一个异步方法完成后才能继续触发。你的问题可能与此有关。

最终,问题的原因是LoadAsync方法在等待填充整个缓冲区(1024字节(时挂起,尽管InputStreamOptions设置为Partial。我得到的异常有点无关,与异步方法工作不正常有关(当第一个任务没有完成时,该方法被再次调用(。

修复是将ReadTimeout添加到串行设备的组合:

_currentSerialDevice.ReadTimeout = TimeSpan.FromMilliseconds(500);

并且还将LoadAsync任务本身封装在定时取消令牌中:

using (var cts = new CancellationTokenSource(500))
{
var task = _dataReader.LoadAsync(ReadBufferLength);
var readTask = task.AsTask(cts.Token);
uint bytesRead = await readTask;
}

这允许LoadAsync方法在设备要消耗的字节数小于1024(由SerialDevice.ReadTimeout处理(时以及在设备要使用的字节数为0(由CancellationToken处理(时完成。

我仍然不确定为什么运行win forms应用程序在一段时间内解决了这个问题,可能是因为它设置了ReadTimeout(而我的UWP应用程序没有设置(,而且这种情况在某种程度上一直存在于串行端口上。

最新更新