C# UWP SerialDevice数据读取器异常:0x800710DD。操作标识符无效

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 :

我正在将一个示例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没有帮助,问题仍然存在

上次它发生时,似乎没有影响我的数据写入器对设备的写入,只是影响了后续的读取

所有代码都在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;
}