【问题标题】:Reading a .NET Stream : high CPU usage - how to read wihtout while (true)?读取 .NET 流:CPU 使用率高 - 如何在没有 while 的情况下读取(真)?
【发布时间】:2014-10-03 10:29:20
【问题描述】:

由于我的问题与这个问题很接近,我一直在寻找这个可能的解决方案的反馈:Reading on a NetworkStream = 100% CPU usage 但我找不到我需要的解决方案。

就像在这个其他问题中一样,我想使用除无限 while 循环之外的其他东西。

更准确地说,我正在使用XamarinVisual Studio 中构建Android 应用程序。因为我需要Bluetooth 服务,所以我使用Stream 来读取和发送数据。

Stream.InputStrem 读取数据是我遇到的问题:是否存在某种阻塞调用来等待数据可用而不使用 while (true) 循环?

我试过了:

  • 开始/结束阅读
  • Task.Run 并等待

这是一个代码示例:

public byte[] RetrieveDataFromStream()
    {
        List<byte> packet = new List<byte>();
        int readBytes = 0;
        while (_inputStream.CanRead && _inputStream.IsDataAvailable() && readBytes < 1024 && _state == STATE_CONNECTED)
        {
            try
            {
                byte[] buffer = new byte[1];
                readBytes = _inputStream.Read(buffer, 0, buffer.Length);

                packet.Add(buffer[0]);
            }
            catch (Java.IO.IOException e)
            {
                return null;
            }
        }
        return packet.ToArray();
    }

我从 while 循环中调用此方法。 此循环将检查直到此方法返回 NULL 以外的其他值,在这种情况下,我将相应地处理数据。

一旦有数据要处理,CPU 使用率就会降低,远低于没有数据要处理的情况。

我知道为什么我的 CPU 使用率很高:循环会尽可能频繁地检查是否有要读取的内容。从好的方面来说,接收数据时几乎没有延迟,但不,这不是一个可行的解决方案。

有什么改变这个的想法吗?

# 更新 1

按照 Marc Gravell 的想法,这是我想了解和尝试的内容:

byte buffer = new byte[4096];
while (_inputStream.CanRead
  && (readBytes = _inputStream.Read(buffer, 0, buffer.Length)) > 0
  && _state == STATE_CONNECTED)
{
    for(int i = 0 ; i < readBytes; i++)
        packet.Add(buffer[i]);
    // or better: some kind of packet.AddRange(buffer, 0, readBytes)
}

你怎么称呼这段代码 sn-p ? 两个问题:

  1. 如果没有可读取的内容,则 while 条件将为 被解雇:下一步该做什么?

  2. 读完之后,接下来要做什么?您如何捕获任何新的传入数据包?

以下是一些应该有所帮助的解释:

  1. android 设备通过蓝牙连接到另一个发送数据的设备。它将始终发送具有指定大小 (1024) 的预先设计的数据包
  2. 该设备可以在一段时间内连续流式传输数据,但也可以在很长一段时间内随时停止。如何处理此类行为?

【问题讨论】:

  • IsDataAvailable() 返回false 时,主要问题似乎是“热循环”。坦率地说,您不需要检查 - 只需Read
  • 谢谢。我会考虑的。如果它没有“破坏”我的算法并创建更小的 CPU 负载:)

标签: android .net bluetooth stream xamarin


【解决方案1】:

立即解决方法是:

  • 不要一次读取一个字节
  • 不要按字节创建新缓冲区
  • 不要在没有可用数据时陷入热循环

例如:

byte buffer = new byte[4096];
while (_inputStream.CanRead
  && (readBytes = _inputStream.Read(buffer, 0, buffer.Length)) > 0
  && _state == STATE_CONNECTED)
{
    for(int i = 0 ; i < readBytes; i++)
        packet.Add(buffer[i]);
    // or better: some kind of packet.AddRange(buffer, 0, readBytes)
}

请注意,在原始while 检查中使用readBytes 看起来有些……困惑;我已将其替换为“当我们没有获得 EOF”检查时;随意添加您自己的逻辑。

【讨论】:

  • 好吧,这种模式我见过几次了,但是……你怎么称呼它?我会更新我的帖子以更精确。谢谢
猜你喜欢
  • 2011-06-09
  • 1970-01-01
  • 2021-11-07
  • 1970-01-01
  • 1970-01-01
  • 2022-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多