C# 处理极小的时间增量

C# 处理极小的时间增量,c#,multithreading,can-bus,C#,Multithreading,Can Bus,好吧,这个标题可能很模糊,但请允许我解释一下 我正在处理一个大列表,其中有数百条消息将作为字节数组发送到CAN总线。每个消息都有一个Interval属性,详细说明必须发送消息的频率(以毫秒为单位)。但我会继续讲下去的 所以我有一根线。线程在这个巨大的消息列表中循环,直到停止,其主体大致如下: Stopwatch timer = new Stopwatch(); sw.Start(); while(!ShouldStop) { foreach(Message msg in list)

好吧,这个标题可能很模糊,但请允许我解释一下

我正在处理一个大列表,其中有数百条消息将作为字节数组发送到CAN总线。每个消息都有一个Interval属性,详细说明必须发送消息的频率(以毫秒为单位)。但我会继续讲下去的

所以我有一根线。线程在这个巨大的消息列表中循环,直到停止,其主体大致如下:

Stopwatch timer = new Stopwatch();
sw.Start();
while(!ShouldStop)
{
   foreach(Message msg in list)
   {
      if(msg.IsReadyToSend(timer)) msg.Send();
   }
}
这非常有效,在尊重消息对象的间隔方面具有惊人的准确性。但是,它占用了整个CPU。问题是,由于大量的消息和CAN总线的性质,在线程必须发送另一条消息之前,通常只有不到半毫秒的时间。线程的睡眠时间永远不会超过15毫秒

我想弄清楚的是,是否有一种方法可以做到这一点,允许线程暂时阻塞或屈服,允许处理器休眠并节省一些周期。如果我尝试将工作拆分为每条消息的一个线程,我会得到任何类型的准确性吗?有没有其他我看不到的方法


编辑:值得一提的是,消息的Interval属性不是绝对的。只要线程继续发出消息,接收方应该很高兴,但如果线程由于高优先级线程窃取其时间片而定期休眠(比如25毫秒),则可能会对接收方发出红旗。

正如您所发现的,在CPU上“等待”的最准确方法是轮询RTC。然而,这是计算密集型的。如果你需要在计时上达到时钟的准确度,没有其他方法

然而,在你原来的帖子中,你说时间大约为15毫秒

在我家的3.3GHz四核i5上,15ms x 3.3GHz=5000万个时钟周期(如果算上所有的核,则为2亿个)

那是永恒的

对于你的目的来说,宽松的睡眠时间很可能是足够准确的


坦率地说,如果您需要硬RT,那么在Windows内核的.net GC上运行的.net VM上的C#是错误的选择。

正如您所发现的,在CPU上“等待”的最准确方式是轮询RTC。然而,这是计算密集型的。如果你需要在计时上达到时钟的准确度,没有其他方法

然而,在你原来的帖子中,你说时间大约为15毫秒

在我家的3.3GHz四核i5上,15ms x 3.3GHz=5000万个时钟周期(如果算上所有的核,则为2亿个)

那是永恒的

对于你的目的来说,宽松的睡眠时间很可能是足够准确的


坦率地说,如果您需要硬RT,那么在Windows内核上的.net GC上运行的.net VM上的C#是错误的选择。

根据更新的要求,使用
睡眠(0)
的默认设置很有可能就足够了-消息可能会以小的突发方式发送,但听起来还可以。使用多媒体定时器可能会使突发事件不那么明显。若可能的话,建立对消息接收者更大的容忍度可能是更好的方法


如果你需要高精度的保证——Windows上的C不是最好的选择——可能需要单独的硬件(甚至是Adruino),或者至少需要C#支持的低级别代码

Windows不是RT操作系统,因此您无法真正获得亚毫秒的精度

若你们需要亚毫秒的精度,那个么你们的忙循环(可能在高优先级线程上)是常用的方法

您可以尝试使用多媒体计时器(示例-),也可以将默认时间片更改为1ms(请参阅示例/说明)

在任何情况下,您都应该意识到,如果有其他更高优先级的线程需要调度,那么您的代码可能会丢失其时间片,并且您的所有工作都将丢失


注意:显然,你应该考虑更合理的数据结构是否更合适(即堆或优先级队列可以更好地找到下一个项目)。

< P>根据更新的要求,默认设置为“代码>睡眠(0)< /代码>的可能性非常大-消息可以以小突发的方式发送,但听起来很好。使用多媒体定时器可能会使突发事件不那么明显。若可能的话,建立对消息接收者更大的容忍度可能是更好的方法


如果你需要高精度的保证——Windows上的C不是最好的选择——可能需要单独的硬件(甚至是Adruino),或者至少需要C#支持的低级别代码

Windows不是RT操作系统,因此您无法真正获得亚毫秒的精度

若你们需要亚毫秒的精度,那个么你们的忙循环(可能在高优先级线程上)是常用的方法

您可以尝试使用多媒体计时器(示例-),也可以将默认时间片更改为1ms(请参阅示例/说明)

在任何情况下,您都应该意识到,如果有其他更高优先级的线程需要调度,那么您的代码可能会丢失其时间片,并且您的所有工作都将丢失


注:显然,你应该考虑更合理的数据结构是否更合适(即堆或优先级队列可以更好地找到下一个项目)。< /P>只需添加<代码>线程。在代码< >()(代码)>(代码)>内睡眠(0)<代码>,以使其发挥良好。如果这是一个GUI应用程序,则您的
while()
不应位于主屏幕上thread@MickySleep(0)将释放剩余的时间片,因此线程可能被安排在大约7-10毫秒(平均)内执行,因此最多会错过20条消息的发送(如“在…发送另一条消息之前不到半毫秒”)@阿列克谢列文科夫听起来是时候打破阿杜伊诺和突破板了!根据更新后的定期睡眠(0)可以接受。试试看。是的,考虑过之后,我想我愿意放弃几毫秒的精度损失。睡眠(0)应该能解决我的问题