5

我正在用 C# 在 WinRT 上编写一个客户端应用程序,它通过 TCP 连接到多个服务器。对于 TCP 连接,我使用 StreamSocket。然后将输入和输出字符串包装在 DataWriter 和 DataReader 中。当我连接到多个服务器时,出现以下异常:“操作标识符无效”

这是该方法的代码:

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 字节。

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

4

2 回答 2

8

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

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

这是修改后的代码片段:

IAsyncOperation<uint> taskLoad = reader.LoadAsync(receiveBufferSize);
taskload.AsTask().Wait();
bytesRead = taskLoad.GetResults();

感谢 Geoff 让我走上了正确的道路:) 我希望我能帮助那些也(将会)遇到这个问题的人。

于 2013-04-20T09:11:21.097 回答
1

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

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

进一步阅读:

LoadAsync 方法只能在 UI 线程上调用一次。在引发 LoadCompleted 事件之前,无法再次调用该方法。无论查询是否成功,都会引发 LoadCompleted 事件。

然后,将它与为什么 async/await 不仅仅是纯粹的魔法酱的这个非常彻底的答案结合起来:

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

所以看起来第二次调用LoadAsync()是在第一次完成之前发生的;两者都是由同一个 UI 线程制成的。

于 2013-04-19T18:08:46.677 回答