我正在尝试通过微 Controller 从传感器的几个串行端口读取数据。每个串行端口将接收2000多个测量值(每个测量值为7字节,均以十六进制表示)。他们在同一时间射击。现在,我正在从4个串行端口进行轮询。另外,我将每个度量转换为String并将其附加到Stringbuilder。当我完成数据接收后,它们将被输出到文件中。问题是CPU消耗非常高,范围从80%到100%。
我浏览了一些文章并将Thread.Sleep(100)放在最后。当没有数据进入时,它减少了CPU时间。当BytesToRead小于100时,我还将Thread.Sleep放在每次轮询的末尾。它仅在一定程度上有所帮助。
有人可以建议一种从串行端口轮询并处理我得到的数据的解决方案吗?也许每次我得到的东西都附加会导致问题?
//I use separate threads for all sensors
private void SensorThread(SerialPort mySerialPort, int bytesPerMeasurement, TextBox textBox, StringBuilder data)
{
textBox.BeginInvoke(new MethodInvoker(delegate() { textBox.Text = ""; }));
int bytesRead;
int t;
Byte[] dataIn;
while (mySerialPort.IsOpen)
{
try
{
if (mySerialPort.BytesToRead != 0)
{
//trying to read a fix number of bytes
bytesRead = 0;
t = 0;
dataIn = new Byte[bytesPerMeasurement];
t = mySerialPort.Read(dataIn, 0, bytesPerMeasurement);
bytesRead += t;
while (bytesRead != bytesPerMeasurement)
{
t = mySerialPort.Read(dataIn, bytesRead, bytesPerMeasurement - bytesRead);
bytesRead += t;
}
//convert them into hex string
StringBuilder s = new StringBuilder();
foreach (Byte b in dataIn) { s.Append(b.ToString("X") + ","); }
var line = s.ToString();
var lineString = string.Format("{0} ---- {2}",
line,
mySerialPort.BytesToRead);
data.Append(lineString + "\r\n");//append a measurement to a huge Stringbuilder...Need a solution for this.
////use delegate to change UI thread...
textBox.BeginInvoke(new MethodInvoker(delegate() { textBox.Text = line; }));
if (mySerialPort.BytesToRead <= 100) { Thread.Sleep(100); }
}
else{Thread.Sleep(100);}
}
catch (Exception ex)
{
//MessageBox.Show(ex.ToString());
}
}
}
最佳答案
这不是一个好方法,最好处理DataReceived事件。
基本上,使用串行端口,可以通过一个3阶段的过程很好地进行工作。
所以像
class DataCollector
{
private readonly Action<List<byte>> _processMeasurement;
private readonly string _port;
private SerialPort _serialPort;
private const int SizeOfMeasurement = 4;
List<byte> Data = new List<byte>();
public DataCollector(string port, Action<List<byte>> processMeasurement)
{
_processMeasurement = processMeasurement;
_serialPort = new SerialPort(port);
_serialPort.DataReceived +=SerialPortDataReceived;
}
private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
while(_serialPort.BytesToRead > 0)
{
var count = _serialPort.BytesToRead;
var bytes = new byte[count];
_serialPort.Read(bytes, 0, count);
AddBytes(bytes);
}
}
private void AddBytes(byte[] bytes)
{
Data.AddRange(bytes);
while(Data.Count > SizeOfMeasurement)
{
var measurementData = Data.GetRange(0, SizeOfMeasurement);
Data.RemoveRange(0, SizeOfMeasurement);
if (_processMeasurement != null) _processMeasurement(measurementData);
}
}
}
注意:“添加字节”会一直收集数据,直到您有足够的计数作为度量值为止;或者,如果您获得大量数据,则将其拆分为单独的度量值...。因此,您可以一次获得1个字节,下次获得2个字节,然后接下来再增加1个,然后将其转换为度量。在大多数情况下,如果您的微型麦克风连发发送,它将成一体出现,但有时会分成2个。
然后在某个地方你可以做
var collector = new DataCollector("COM1", ProcessMeasurement);
和
private void ProcessMeasurement(List<byte> bytes)
{
// this will get called for every measurement, so then
// put stuff into a text box.... or do whatever
}
关于c# - 串行端口轮询和数据处理,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15124132/