读取.NET流:CPU占用率高 - 如何在没有读取的情况下读取(true)?

时间:2014-10-03 10:29:21

标签: android .net bluetooth stream xamarin

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

就像在另一个问题中一样,我想使用其他东西而不是无限循环。

更确切地说,我使用XamarinAndroid中构建Visual Studio应用程序。由于我需要Bluetooth服务,因此我使用Stream来读取和发送数据。

Stream.InputStrem读取数据是我遇到问题的地方:是否有某种阻止调用等待数据可用而不使用while(true)循环?< / p>

我试过了:

  • 开始/结束阅读
  • 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使用率很高:如果有东西要读,循环会尽可能频繁地检查。从好的方面来说,收到数据时几乎没有延迟,但不是,这不是一个可行的解决方案。

有任何改变这个想法吗?

#UPDATE 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)
}

您如何调用此代码段? 两个问题:

  1. 如果没有什么可读,那么while条件就是 被解雇:接下来要做什么?

  2. 一旦你完成阅读,你接下来会做什么?如何捕获任何新的传入数据包?

  3. 以下是一些有用的解释:

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

1 个答案:

答案 0 :(得分: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)
}

请注意,在原始readBytes支票中使用while看起来有点混乱;我用#34替换了它;而我们没有得到EOF&#34;校验;随意添加自己的逻辑。