Await没有给出结果

时间:2016-09-13 15:09:11

标签: c# .net asynchronous networking async-await

好的,我有一些代码可以呈现。这是NetworkStream对象的扩展方法。

public async static Task<byte[]> ReadDataAsync(this NetworkStream clientStream)
{
    byte[] data = {};

    var buffer = new byte[1024];
    if (clientStream.CanRead)
    {
        using (var ms = new MemoryStream())
        {
            try
            {
                int bytesRead;
                while (clientStream.DataAvailable && 
                  (bytesRead = await clientStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                {
                    await ms.WriteAsync(buffer, 0, bytesRead);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                return data;
            }

            data = ms.ToArray();
        }
    }
    else
    {
        Console.WriteLine("Closing clientStream.");
        clientStream.Close();
    }
    return data;
}

我尝试调用此方法的代码。

public async static Task Preform(Socket client)
{
    var stream = new NetworkStream(client);
    var data = await stream.ReadDataAsync();
    var message = await MessageFabrique.DeserializeMessage(data);

    ServerCollections.Instance.ServerIssueQueue.Add(new ServerIssue
    {
        Message = message,
        ClientStream = stream
    });
}

ReadDataAsync方法总是将我返回到一个空数组。在我尝试反序列化数据的那一刻,有一个例外 - 因为data[0]。请帮我。为什么会发生这种情况,如果await 保证我的结果,何时需要?

3 个答案:

答案 0 :(得分:4)

clientStream.DataAvailable并不意味着将来可能会出现数据。这意味着现在可以使用数据进行阅读。摆脱它并且只是读取,读取将阻塞直到数据显示或当流命中它结束时将返回0。

答案 1 :(得分:0)

斯科特的答案是对的,但.Net已经照顾好你了......

您可以考虑Stream.CopyToAsync

changeMyDB

代码中出错的地方要少得多。

答案 2 :(得分:0)

除了其他答案之外,您可能还想创建同步上下文。有关详细信息,请参阅this article

摘要是async / await在控制台应用程序中的工作方式与在UI应用程序中的工作方式不同。默认情况下,WPF和WebForms应用程序具有同步上下文,但控制台应用程序不具备此功能。结果(实际上非​​常明显&#34;广告宣传效果不佳&#34;在文档中)是async / await的行为 在控制台应用程序中的可预测性低于在UI应用程序中的行为,这可能会使它无法正常工作&#34;正如所宣传的那样#34;在某些情况下。

例如,在UI应用程序中&#34; async&#34;并不一定意味着代码在后台线程上运行。这相当于&#34;我准备好后再回到我身边。&#34;作为类比,考虑出去和10个人一起吃饭:当服务员来的时候,他要求订购的第一个人还没有准备好。这里的两个不好的解决方案是:a)引入第二个服务员等待第一个人准备好或接受其他9个人的命令)或b)等到第一个人准备好开始接受订单。最好的方法是接受其他9个人的命令然后回到第一个希望他到那时准备好的人。过度简化的风险基本上是异步在UI中的工作原理(除非你明确地将代码放在后台线程上,使用像Task.Run这样的东西)。但是,在使用异步的控制台应用程序中,无法保证代码实际运行的位置。

但是,如果您按照我链接到它的文章中所述添加同步上下文,则会以更加可预测的方式运行。