首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >UWP SerialDevice DataReader异常: 0x800710DD。操作标识符无效

UWP SerialDevice DataReader异常: 0x800710DD。操作标识符无效
EN

Stack Overflow用户
提问于 2020-03-27 18:10:27
回答 2查看 398关注 0票数 0

我正在致力于将功能从一个示例Windows Forms App移植到一个Xamarin.Forms UWP应用程序,在那里它应该在COM端口上对蓝牙设备进行写入和读取。我让它在大多数情况下都工作得很好,但UWP应用程序会间歇性地让自己进入一种状态,任何对dataReader.LoadAsync的调用都会触发异常:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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项目中。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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);
    }
}

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Get serial devices
DeviceInformationCollection serialDeviceCollection = await DeviceInformation.FindAllAsync(SerialDevice.GetDeviceSelector());
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 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;
}

用于写入设备的代码,即使在设备处于奇怪状态时也能正常工作:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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应用程序中的问题一段时间,允许我再次从设备读取。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-03-30 17:03:22

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

修复方法是将ReadTimeout添加到SerialDevice中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
_currentSerialDevice.ReadTimeout = TimeSpan.FromMilliseconds(500);

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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应用程序没有),并且以某种方式在串口上持续存在。

票数 0
EN

Stack Overflow用户

发布于 2020-03-30 01:45:41

这可能与异步方法有关。您可以尝试这样做:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var task = await _dataReader.LoadAsync(ReadBufferLength);
task.AsTask().Wait();
uint bytesRead = task.GetResults();

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60891802

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文