【问题标题】:WinRT: DataReader.LoadAsync Exception with StreamSocket TCPWinRT:StreamSocket TCP 的 DataReader.LoadAsync 异常
【发布时间】:2013-04-19 17:45:39
【问题描述】:

我正在用 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 字节。

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

【问题讨论】:

  • 您的意思是“当我连接到多个一个服务器时?”
  • @Geoff 是的,对不起。我的意思是“..到多个服务器”

标签: c# winrt-async


【解决方案1】:

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

有了这个答案 (How to integrate WinRT asynchronous tasks into existing synchronous libraries?),我将 LoadAsync 方法写入了一个同步方法,现在它可以工作了,因为同一个线程正在调用该方法并使用它的结果。

这是修改后的代码片段:

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

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

【讨论】:

    【解决方案2】:

    在我看来,异常的可能原因是这篇文章from the documentation

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

    进一步阅读:

    LoadAsync 方法只能在 UI 线程上调用一次。这 直到 LoadCompleted 事件结束后才能再次调用方法 提高。无论查询与否,都会引发 LoadCompleted 事件 成功。

    然后,将其与 this very thorough answer 结合起来,了解为什么 async/await 不仅仅是纯粹的魔法酱:

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

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

    【讨论】:

    • 感谢您的回答,但我认为您查找了错误的方法。我正在使用的 DataReader(带有 StreamSocket-Stream 输入)记录在此处:msdn.microsoft.com/library/windows/apps/BR208119
    • 啊,你是对的。鉴于正确的文档是多么稀少,您可能至少需要调查在另一个线程中运行 LoadAsync 调用是否有助于解决问题。
    • 好的,我现在找到了解决方案。我使 LoadAsync 被称为阻塞而不是异步/等待。我会尽快回答我的问题。 (stackoverflow 阻止新用户在 8 小时内回答他们的问题...)
    猜你喜欢
    • 2014-02-17
    • 1970-01-01
    • 1970-01-01
    • 2018-03-11
    • 2020-05-03
    • 1970-01-01
    • 2016-03-19
    • 2012-05-29
    • 1970-01-01
    相关资源
    最近更新 更多