我正在研究电压表应用程序,该应用程序绘制电压波形。硬件每秒通过串行端口以字符串格式发送1000个数字(范围为0-1023,始终为整数)。
public SerialPort serialPort = new SerialPort("COM3", 57600);
serialPort.Open();
将字符串转换为int,然后使用DrawLine将其绘制到PictureBox中。
// variable declarations, all is int, runs in its own thread
while (blToMeasure) // true after clicking on button
{
iPrevY = iY;
iY = Int16.Parse(serialPort.ReadLine());
graphicsGraph.DrawLine(penBlack, iX, iPrevY, iX + 1, iY);
// only this thread is accessing PictureBox
iX++;
if (iX > picBoxGraph.Width)
{
graphicsGraph.Clear(SystemColors.Control);
iX = 0;
}
if (iY > picBoxGraph.Height)
{
}
}
问题在于,画线本身速度很快,只需要几秒钟,但逐渐变慢。
我尝试了Int.Parse
,Int32.Parse
,并使用lock (graphicsGraph)
(将带有Clear的条件移动到另一个线程中)或使用BlockingCollection<int>
(将DrawLine移到了另一个线程中)以多种方式拆分线程功能,远离Parse)。似乎一无所获,运行一分钟后,应用仍然变慢了几次。
硬件本身没有问题,请使用其他软件进行检查。这对于C#来说太快了吗?
答案 0 :(得分:0)
使用Port.ReadTimeout = 1
和Port.DiscardInBuffer()
可获得最佳结果。也使用Form.DoubleBuffered = true
,但在这种情况下并没有太大的区别。
// constructor
Port.ReadTimeout = 1;
Form.DoubleBuffered = true;
这是循环本身:
btn.Click() // click to start measuring
{
Port.DiscardInBuffer();
blToMeasure = true;
}
while (blToMeasure) // true after clicking on button
{
iPrevY = iY;
try {
iY = Int16.Parse(serialPort.ReadLine());
}
catch
{
// exception logic
}
graphicsGraph.DrawLine(penBlack, iX, iPrevY, iX + 1, iY);
// only this thread is accessing PictureBox
iX++;
if (iX > picBoxGraph.Width)
{
graphicsGraph.Clear(SystemColors.Control);
iX = 0;
}
if (iY > picBoxGraph.Height)
{
}
}
当应用程序开始从端口读取数据时,总是有累积的数据,因为我的硬件一直在发送数字,所以我摆脱了缓冲区。比绘制线条不会以不同的尖峰执行,并且速度是恒定的。通过分析Watch
的问题,我发现,读取该数据有时会花费更长的时间,并且由于每秒读取1000次,因此速度变慢。因此,为了避免速度变慢,我使用了Port.ReadTimeout
,如果读取时间太长,则会跳过读取。
差异是显而易见的,绘画不再减慢速度,并且与我尝试的时间保持几分钟的相同速度。我认为这是解决我问题的足够方法,谢谢!