WinRT: DataReader.LoadAsync Exception with StreamSocket TCP

本文关键字:with StreamSocket TCP Exception LoadAsync DataReader WinRT | 更新日期: 2023-09-27 18:10:00

我正在用c#编程WinRT上的客户端应用程序,该应用程序通过TCP连接到多个服务器。对于TCP连接,我使用StreamSocket。然后将输入和输出字符串包装在数据写入器和数据读取器中。当我连接到多个服务器时,我得到以下例外:"操作标识符无效"

方法的代码:

private async void read()
    {
        while (true)
        {
            uint bytesRead = 0;
            try
            {
                bytesRead = await reader.LoadAsync(receiveBufferSize);
                if (bytesRead == 0)
                {
                    OnClientDisconnected(this);
                    return;
                }
                byte[] data = new byte[bytesRead];
                reader.ReadBytes(data);
                if (reader.UnconsumedBufferLength > 0)
                {
                    throw new Exception();
                }
                OnDataRead(this, data);
            }
            catch (Exception ex)
            {
                if (Error != null)
                    Error(this, ex);
            }
            new System.Threading.ManualResetEvent(false).WaitOne(10);
        }
    }

Stacktrace只显示reader。LoadAsync(UInt32 count)方法作为问题的根源。每个ClientInstance运行在自己的任务中,并拥有自己的DataReader和Stream实例。"receiveBufferSize"为8192字节。

你知道可能是什么错误吗?

WinRT: DataReader.LoadAsync Exception with StreamSocket TCP

我想我现在可以自己回答问题了。问题是,LoadAsync方法不能很好地与await/async结构一起工作。该方法由线程池线程A调用,然后由线程池线程b恢复(在等待之后)。这个星座抛出了异常。但我不能确切地说为什么……

用这个答案(如何将WinRT异步任务集成到现有的同步库中?)我把LoadAsync方法写进了一个同步方法,现在它可以工作了,因为同一个线程正在调用这个方法并使用它的结果。

下面是修改后的代码片段:
IAsyncOperation<uint> taskLoad = reader.LoadAsync(receiveBufferSize);
taskload.AsTask().Wait();
bytesRead = taskLoad.GetResults();

感谢Geoff把我带到了正确的道路上。我希望我能帮助那些同样有这个问题的人。

在我看来,异常的可能原因是文档中的这一段:

当之前对LoadAsync的调用尚未完成时。

往下读:

LoadAsync方法只能在UI线程中调用一次。的方法不能再次调用,直到LoadCompleted事件结束提高。无论是否执行查询,都会引发LoadCompleted事件成功。

然后,把它和下面这个关于为什么async/await不是纯粹的魔法酱的非常彻底的答案结合起来:

[…await不会神奇地导致同步方法运行异步。它不会启动一个新线程并运行该方法例如,在新线程上。

因此,对LoadAsync()的第二次调用似乎发生在第一次调用完成之前;