当我在RaspberryPi上尝试从Linux的串口(uart)读取数据时,在循环中总是得到5-10%的CPU负载。因为SerialPorts应该是阻塞的,所以这不应该使用那么多的cpu负载,或者我错了?
我试了两个代码:
简单代码
var port = new SerialPort("/dev/ttyUSB0", 57600);
port.Open();
while (true)
{
if (port.BytesToRead > 0)
{
while (port.BytesToRead > 0)
Console.Write($"{port.ReadByte().ToString("X2")} ");
Console.WriteLine("");
}
Thread.Sleep(100);
}高级代码
static int blockLimit = 100;
static void Main(string[] args)
{
var port = new SerialPort("/dev/ttyUSB0", 57600);
port.Open();
byte[] buffer = new byte[blockLimit];
Action kickoffRead = null;
kickoffRead = delegate
{
port.BaseStream.BeginRead(buffer, 0, buffer.Length, delegate (IAsyncResult ar)
{
try
{
int actualLength = port.BaseStream.EndRead(ar);
byte[] received = new byte[actualLength];
Buffer.BlockCopy(buffer, 0, received, 0, actualLength);
raiseAppSerialDataEvent(received);
}
catch (IOException exc)
{
handleAppSerialError(exc);
}
kickoffRead();
}, null);
};
kickoffRead();
while (true)
Thread.Sleep(1000);
}
private static void handleAppSerialError(IOException exc)
{
throw new NotImplementedException();
}
private static void raiseAppSerialDataEvent(byte[] received)
{
Console.WriteLine(BitConverter.ToString(received));
}两者都有相同的结果:两个进程一起使用5%到10%的cpu负载

在运行HypriotOS 1.10.0的RaspberryPi 3b+上使用.NET Core 3.0 Preview 2和System.IO.Ports 4.6.0-preview-19073.11
发布于 2020-02-03 04:24:26
至于现在(NET Core3.1)的SerialPort实现是非常占用CPU资源的。根据dima117 response here .NET Core - Use System.IO.Ports.SerialPort in visual studio code,我已经将Mono SerialPort移植到Net标准库
我已经将它发布到github:
https://github.com/michaldobrodenka/System.IO.Ports.Mono
有了这个SerialPort实现,我的allwinner h3硬件上的CPU使用率从25%下降到5%
发布于 2021-01-09 00:02:36
我也遇到过同样的问题,并使用Jetbrains的dotTrace进行了一些分析。我得到了以下信息:
7.71% Poll • 25,862/25,862 ms • Interop+Serial.Poll(SafeHandle, PollEvents, Int32, out PollEvents)
7.71% PollEvents • System.IO.Ports.SerialStream.PollEvents(Int32, Boolean, Boolean, out Nullable)
7.71% IOLoop • System.IO.Ports.SerialStream.IOLoop
7.71% InnerInvoke • System.Threading.Tasks.Task.InnerInvoke
Thread #87procent和我在运行top -d 1时看到的差不多。
看一下被调用的方法,我假设使用了轮询,这不是很有效。特别是如果轮询间隔非常短的话。因此,我查看了GitHub上的dotnet源代码,并注意到间隔被硬编码为1ms(845行)。
Interop.PollEvents events = PollEvents(
1,
pollReadEvents: hasPendingReads,
pollWriteEvents: hasPendingWrites,
out Interop.ErrorInfo? error);我会看看我是否可以在GitHub存储库创建一个问题。
https://stackoverflow.com/questions/54903630
复制相似问题