【发布时间】:2018-08-01 19:56:59
【问题描述】:
我有两个线程。一种是从串行端口收集数据并将其放入一个数组中,然后将其添加到并发队列中。另一个线程正在获取这些数组并实时绘制数据。每秒大约有 150 个 50 字节的数据包。 我遇到的问题是,当它运行时,它会消耗大约 10% 的 CPU。这是在非常快的核心 I7 Haswell 上。如果我在消费线程中添加 Thread.Sleep(1),那么 CPU 利用率会下降到 1%。问题是如果我把它放在 Thread.Sleep(2) 上,那么数据包就不再同步了。所以这不是一个解决方案,如果它在较慢的计算机上运行,它可能无法正常工作。
代码很简单。这是生产者线程:
static void FillQueue(byte[] buffer)
{
dataQueue.Enqueue(buffer);
}
这里是消费者线程:
while (continuePolling)
{
Thread.Sleep(1); //if removed, there is 10% CPU utilization. If higher then packet synchronization is lost.
if (dataQueue.TryDequeue(out result))
{
ProcessPacket(result);
}
}
我觉得这很难理解,因为 ProcessPacket 方法执行大约需要 0.3 毫秒,并且每秒调用大约 10 次。
我现在尝试改用阻塞集合。 这里是制作人
BlockingCollection<byte[]> dataQueue = new BlockingCollection<byte[]>;
public static void addData(buffer)
{
dataQueue.add(buffer);
}
这里是消费者
while (dataQueue.TryTake(out result)
{
ProcessPacket(result);
}
根本没有区别!它使用 10% 的 CPU,如果我添加一个 Thread.Sleep(1) 就可以了,但是一个 Thread.Sleep(2) 我会丢失数据包 我不明白。每个数据包有 50 个字节。而已。它们的消耗速度与生产速度一样快。 谢谢
【问题讨论】:
-
听起来您没有在串行端口上使用异步 I/O。向我们展示 I/O 代码
-
考虑使用
BlockingCollection而不是ConcurrentQueue以避免需要Thread.Sleep调用(使用阻塞Take方法)。 -
@MickyD 串行 I/O 花费的时间不到一毫秒,并且该线程不是瓶颈。如果我注释掉消费者,那么就没有性能问题。
标签: c# .net multithreading concurrency queue