C# NetworkStream上的ReadAsync似乎正在使用我所有的CPU
我有下面的方法,它异步地从C# NetworkStream上的ReadAsync似乎正在使用我所有的CPU,c#,asynchronous,profiling,networkstream,C#,Asynchronous,Profiling,Networkstream,我有下面的方法,它异步地从NetworkStream读取和反序列化数据包。一切都正常,但CPU评测显示,我等待异步读取的最后一行是我大部分CPU使用的来源 我是否实现得很糟糕/效率低下,或者NetworkStream的异步实现本身有什么问题 public async Task<Packet> ReadAsync(CancellationToken cancellationToken) { while (true) { // Read through t
NetworkStream
读取和反序列化数据包。一切都正常,但CPU评测显示,我等待异步读取的最后一行是我大部分CPU使用的来源
我是否实现得很糟糕/效率低下,或者NetworkStream
的异步实现本身有什么问题
public async Task<Packet> ReadAsync(CancellationToken cancellationToken)
{
while (true)
{
// Read through the available bytes until we find the start of a packet
while (start < length && buffer[start] != Packet.STX)
start++;
// Align the packet (and all successive bytes) with the beginning of the buffer
if (start > 0)
{
if (start < length)
Array.Copy(buffer, start, buffer, 0, length - start);
length -= start;
start = 0;
}
// Read through the available bytes until we find the end of the packet
while (end < length && buffer[end] != Packet.ETX)
end++;
// If we have a whole packet in the buffer, deserialize and return it
if (end < length)
{
byte[] data = new byte[end + 1];
Array.Copy(buffer, data, end + 1);
byte[] decoded = null;
Packet packet = null;
try
{
decoded = Packet.Decode(data);
}
catch (Exception ex)
{
throw new IOException("Could not decode packet", ex);
}
if (decoded != null)
{
try
{
packet = Packet.Deserialize(decoded);
}
catch (Exception ex)
{
throw new IOException("Could not deserialize packet", ex);
}
}
Array.Copy(buffer, end + 1, buffer, 0, length - (end + 1));
length -= end + 1;
end = 0;
if (packet != null)
return packet;
}
// If we read all available bytes while looking for the end of a packet
if (end == length)
{
if (length == buffer.Length)
throw new InsufficientMemoryException();
length += await Stream.ReadAsync(buffer, length, buffer.Length - length, cancellationToken);
}
}
}
公共异步任务ReadAsync(CancellationToken CancellationToken)
{
while(true)
{
//读取可用字节,直到找到数据包的开头
while(start我已将代码更新为在每次调用
ReadAsync
之间休眠,大致相当于上次读取所用的时间:
var stopwatch = new Stopwatch();
var iteration = 0;
while (true)
{
// ...
var delay = stopwatch.Elapsed;
stopwatch.Restart();
if (iteration % 10 != 0)
await Task.Delay(delay);
length += await Stream.ReadAsync(buffer, length, buffer.Length - length, cancellationToken);
stopwatch.Stop();
iteration += 1;
}
这大大降低了CPU的使用率。这肯定是一个解决办法,因为它没有解决这个问题,但它是有效的。我很想听听其他人对这个问题的回答或意见。我猜“这不是最终的假设”。ReadAsync必须进行系统调用才能将流读入缓冲区。代码的其余部分似乎没有做很多工作。评测是否认识到一个异步方法在几秒钟内没有返回,它本身没有使用该时间跨度?真正的问题是,在所有这些进行时,任务管理器之类的东西对CPU有何影响。我可以向您保证,
NetworkStream
的.NET实现没有问题。你的帖子中也没有任何东西支持“你所有的CPU”都被使用的说法。如果没有详细信息,如a和关于您正在使用的探查器以及(如果适用)您正在使用的探查模式(例如采样或检测),甚至不可能重现您的声明,更不用说解释了。对于您的声明,“NetworkStream的.NET实现NetworkStream
”,那怎么办?我的问题和你描述的一样。除了睡觉或耽搁之外,我一直没能弄明白。我希望有一个更好的解决方案,但我想这将不得不做。为什么你有延迟去,因为阅读时间长?我想,一个简单的10毫秒就足够了。我们的客户往往每分钟左右发送一次请求,每个请求都包含在一个TCP数据包中。我想如果我有几千个连接调用任务,我仍然会看到高CPU使用率。我想每10毫秒延迟一次。一旦我对性能感到满意,我基本上就停止了实现,所以可能还有改进的空间,但我们还不需要它。