我有这样的代码:
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()
,但:
NetworkStream.ReadAsync
希望传递一个byte[]
,但不会返回它,所以我不能简单地return stream.Read(...)
NetworkStream
似乎没有告诉您有多少字节可供读取。stream.Read
,只需传回null。因此,不管上述方法中的问题-我知道它都不是最佳方法-我该怎么做?
目标是我可以做到的,或者等同。
byte [] bytes = await x.Read();
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)可以减少某些操作的内存分配数量