2014-10-03 63 views
1

由于我的问题已经接近这个问题,所以我从这个可能的解决方案反馈回来:Reading on a NetworkStream = 100% CPU usage但我找不到我需要的解决方案。读取.NET流:高CPU使用率 - 如何阅读wihtout while(true)?

就像在这个其他问题一样,我想使用别的东西而不是无限的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

按照马克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. 一旦你读完了,你接下来会做什么?你做什么来捕获任何新的传入数据包?

这里有一些解释,应该帮助:

  1. 该机器人装置被连接,通过蓝牙,向发送数据的另一装置。它会一直发送一个指定大小的预先设计的数据包(1024)。该设备可以连续流式传输数据一段时间,但也可以在任何时间长时间停止。如何处理这种行为?
+0

当IsDataAvailable()返回false时,存在的主要问题是“热循环”。坦率地说,你*不需要检查* - 只是'读' – 2014-10-03 10:40:50

+0

谢谢。我会考虑它。如果它不“破坏”我的算法并创建一个较小的CPU负载:) – Mackovich 2014-10-03 12:28:05

回答

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检查看起来有点......困惑;我用“虽然我们没有得到EOF”检查取代它;随时添加您自己的逻辑。

+0

好吧,我已经看过这种模式几次了,但是......在哪里以及如何调用它?我会更新我的帖子以更精确。谢谢 – Mackovich 2014-10-03 12:26:45