C# UWP SerialDevice数据读取器异常:0x800710DD。操作标识符无效
我正在将一个示例Windows窗体应用程序的功能移植到Xamarin.Forms UWP应用程序,在该应用程序中,它应该在COM端口上向蓝牙设备进行写入和读取。我让它大部分时间都工作正常,但UWP应用程序会间歇性地进入一种状态,任何对dataReader.LoadAsync的调用都会触发异常:C# UWP SerialDevice数据读取器异常:0x800710DD。操作标识符无效,c#,uwp,serial-port,C#,Uwp,Serial Port,我正在将一个示例Windows窗体应用程序的功能移植到Xamarin.Forms UWP应用程序,在该应用程序中,它应该在COM端口上向蓝牙设备进行写入和读取。我让它大部分时间都工作正常,但UWP应用程序会间歇性地进入一种状态,任何对dataReader.LoadAsync的调用都会触发异常: Exception thrown at 0x74AF1A62 (KernelBase.dll) in MyApp.UWP.exe: WinRT originate error - 0x800710DD :
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没有帮助,问题仍然存在
上次它发生时,似乎没有影响我的数据写入器对设备的写入,只是影响了后续的读取
所有代码都在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);
}
}
写入设备的代码,即使设备处于奇数状态也能工作:
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\u dataReader.LoadAsync(ReadBufferLength);
task.AsTask().Wait();
uint bytesRead=task.GetResults();
对于异步方法(例如
DataReader.LoadAsync
),事件发生在UI线程上,只能触发一次,并且只能在上一个异步方法完成后继续触发。您的问题可能与此有关。最后发现问题的原因是LoadAsync方法在等待填充整个缓冲区(1024字节)时挂起,尽管InputStreamOptions设置为Partial。我遇到的异常有些不相关,与异步方法工作不正常有关(在第一个任务尚未完成时再次调用该方法)
该修复是将ReadTimeout添加到SerialDevice的组合:
_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应用程序没有设置),并且以某种方式在串行端口上保持不变。感谢您的帮助,它让我看到这项任务被搁置了很长时间,让我走上了正确的轨道,找到了真正的问题。
_currentSerialDevice.ReadTimeout = TimeSpan.FromMilliseconds(500);
using (var cts = new CancellationTokenSource(500))
{
var task = _dataReader.LoadAsync(ReadBufferLength);
var readTask = task.AsTask(cts.Token);
uint bytesRead = await readTask;
}