处理极小的时间增量
本文关键字:时间 极小 处理 | 更新日期: 2023-09-27 18:32:38
好吧,这个标题可能很模糊,但请允许我解释一下。
我正在处理一个很大的列表,其中包含数百个消息,这些消息将作为字节数组发送到CAN总线。其中每条消息都有一个 Interval 属性,该属性详细说明了必须发送消息的频率(以毫秒为单位(。但我会回到那个。
所以我有一个线程。线程循环浏览这个巨大的消息列表,直到停止,正文大致如下所示:
Stopwatch timer = new Stopwatch();
sw.Start();
while(!ShouldStop)
{
foreach(Message msg in list)
{
if(msg.IsReadyToSend(timer)) msg.Send();
}
}
这非常有效,在遵循消息对象的间隔方面具有惊人的准确性。但是,它占用了整个CPU。问题在于,由于大量的消息和CAN总线的性质,线程必须发送另一条消息之前通常只有不到半毫秒的时间。永远不会有线程能够休眠超过 15 毫秒的情况。
我想弄清楚的是,是否有一种方法可以做到这一点,允许线程阻塞或暂时屈服,允许处理器休眠并节省一些周期。如果我尝试将工作拆分为每条消息的线程,我会得到任何准确性吗?还有其他我没有看到的方法吗?
编辑:值得一提的是,消息的间隔属性不是绝对的。只要线程继续喷出消息,接收方就应该很高兴,但如果线程因为优先级更高的线程窃取其时间片而定期休眠 25 毫秒,它可能会为接收方发出危险信号。
根据更新的要求,很有可能使用Sleep(0)
的默认设置就足够了 - 消息可能会以小的突发方式发送,但听起来没问题。使用多媒体定时器可能会使突发不太明显。建立对消息接收者的更大容忍度可能是更好的方法(如果可能的话(。
如果您需要硬毫秒级精度和良好的保证 - Windows上的C#不是最佳选择 - 可能需要单独的硬件(甚至Adruino(,或者至少需要C#的较低级别的代码。
Windows不是RT操作系统,所以你不能真正获得亚毫秒级的准确性。
如果您需要亚毫秒级精度,则繁忙循环(可能在高 pri 线程上(是常见的方法。
可以尝试使用多媒体计时器(示例 - C# 中的多媒体计时器中断(前两个中断错误((,也可以将默认时间片更改为 1 毫秒(有关示例/说明,请参阅为什么 .NET 计时器的分辨率限制为 15 毫秒?
在任何情况下,您都应该知道,如果有其他更高优先级的线程要调度,您的代码可能会丢失其时间片,并且您的所有努力都将丢失。
注意:您显然应该考虑更合理的数据结构是否更合适(即堆或优先级队列可能更适合查找下一项(。
正如您已经发现的,在CPU上"等待"的最准确方法是轮询RTC。但是,这是计算密集型的。如果您需要在计时中达到时钟精度,则没有其他方法。
但是,在您的原始帖子中,您说时间在 15 毫秒左右。
在我家里的 3.3GHz 四核 i5 上,15ms x 3.3GHz = 5000 万个时钟周期(如果算上所有内核,则为 2 亿个(。
那是永恒。
松散的睡眠时间很可能足够准确,可以满足您的目的。
坦率地说,如果您需要硬RT,在Windows内核上的.net GC上运行的.net VM上的C#是错误的选择。