我如何实现此阻塞Socket方法的基于TcpClient / NetworkStream的异步端口?

问题描述 投票:0回答:1

我有这样的代码:

  public byte[] Read()
  {
     try
     {
        if (ClientSocket.Available != 0)
        {
           var InBuffer = new byte[ClientSocket.Available];
           ClientSocket.Receive(InBuffer);
           return InBuffer;
        }
        else
        {
           return null;
        }

     }
     catch (Exception ex)
     {
        Console.WriteLine(ex.ToString());
     }

  }

我想在不完全更改代码流(疣和所有代码)的情况下使async等效,而我遇到了问题,我也想切换到NetworkStream,因为它已内置在async中方法

我希望信号为Task<byte[]> Read(),但:

  1. NetworkStream.ReadAsync希望传递一个byte[],但不会返回它,所以我不能简单地return stream.Read(...)
  2. NetworkStream似乎没有告诉您有多少字节可供读取。
  3. 如果没有可用数据,我不想调用stream.Read,只需传回null。

因此,不管上述方法中的问题-我知道它都不是最佳方法-我该怎么做?

目标是我可以做到的,或者等同。

byte [] bytes = await x.Read();

c# task-parallel-library
1个回答
0
投票

NetworkStream.ReadAsync就像我遇到的大多数“给我一个字节缓冲区”方法一样;您给它一个字节数组,并要求它从网络中读取X个字节并将其放入缓冲区。它的读物可能比您要求的要少,但不会读得更多。它返回读取的字节数。在任何时候,您的代码都会保留字节数组缓冲区,因此您最终将执行以下操作:

byte[] buf = new byte[4096];
int bytesRead = await networkStream.ReadAsync(buf, 0, buf.Length. someCancelationToken);

byte[] rtn = new byte[bytesRead];
Array.Copy(buf, 0, rtn, 0, rtn.Length);

return rtn;

也就是说,您以异步操作读取,然后返回一个大小为恰好报告为读取的字节数的数组,该数组来自缓冲区。使用此代码的方法将返回Task

还有一个ReadAsync重载,它从您那里接受一个Memory作为缓冲区。您将以类似的方式使用它,只是当您知道已读取多少字节时将在其上调用Slice方法,以返回仅查看缓冲区那部分的Memory。如果您随后在Slice调用的结果上调用ToArray,则会得到一个大小适合您喜好的数组(读取的字节)。在这种情况下,两者之间可能几乎没有什么区别,尽管使用Memory(及其相关类Span)可以减少某些操作的内存分配数量

© www.soinside.com 2019 - 2024. All rights reserved.