繁体   English   中英

等待未给出结果

[英]Await doesn't give a result

好的,我要提供一些代码。 这是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 保证结果呢?

clientStream.DataAvailable并不意味着将来可能会显示数据。 这意味着数据现在可供读取。 摆脱它,然后进行读取,读取将阻塞直到数据显示出来,或者在流到达末尾时返回0。

斯科特的答案是正确的,但是.Net已经照顾到您...

您可能会考虑Stream.CopyToAsync

await clientStream.CopyToAsync(ms)

代码出错的地方少得多。

除了其他答案,您可能还想创建一个同步上下文。 有关详细信息,请参见本文

摘要是,异步/等待在控制台应用程序中的工作方式与在UI应用程序中的方式不同。 WPF和WebForms应用程序默认情况下具有同步上下文,而控制台应用程序则没有。 结果(在文档中实际上是“广告效果很差”)是控制台应用程序中异步/等待的行为比UI应用程序中的行为要难得多 ,并且这可能使其无法“广告效果” “ 在某些情况下。

例如,在UI应用程序中,“异步”并不一定意味着代码在后台线程上运行。 这相当于“等我准备好以后再回来找我”。 打个比方,考虑出去和10个人一起吃饭:当服务员过来时,他要点的第一个人还没有准备好。 这里有两个不好的解决方案:a)引入第二个服务员,要么等待第一个家伙准备好或者接受其他9个人的订单),要么b)等到第一个家伙准备开始接受订单。 最好的办法是接受其他9个人的命令,然后回到第一个人希望他到那时能准备好。 基本上有可能过度简化这是UI中异步工作的方式(除非您使用Task.Run之类的东西将代码显式地放在后台线程中)。 但是,在控制台应用程序中,当您使用异步时,无法保证代码将在何处实际运行。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM