C# - 使用Thread.Sleep()让我的循环每秒运行几百次

时间:2014-01-26 14:20:52

标签: c# multithreading

我正在开发一个分析实时财务数据的应用程序。目前我的主要计算周期有以下设计:

long cycle_counter=0;
while (process_data)
{
  (analyse data, issue instruction - 5000 lines of straightforwasrd code with computations)
  cycle_counter++;
  Thread.Sleep(5);
}

当我在我的笔记本(一个Core i5)处理器上运行此应用程序时,该循环每秒运行200-205次 - 这是一种预期的(如果你不打扰为什么它每秒运行超过200次)。

但是,当我在具有2个6核Xeon处理器和24 GB快速RAM的“真实”工作站上部署应用程序,并且在大约3秒内加载Win7时,应用程序每秒运行大约67次。

我的问题是:

  • 为什么会这样?

  • 在这种情况下,如何影响每秒的运行次数?

  • 有没有更好的解决方案,每秒运行200-1000次循环?我现在正在考虑删除Thread.Sleep()(我在这里使用它的方式受到了很多批评)。有12个内核,我只使用一个内核就可以解决这个问题。但是我的解决方案有些不足之处?

感谢您的想法。

6 个答案:

答案 0 :(得分:6)

你所采取的方法根本就是打破了。轮询策略通常是一种不好的方法,任何时候你因为“我想把剩下的时间片还给操作系统”以外的原因而进行睡眠,你可能做错了。

解决问题的更好方法是:

  • 制作未处理作品的线程安全队列
  • 制作一个将新作品放入队列的线程
  • 创建n个线程,将工作从队列中取出并完成工作。 n应该是你拥有的CPU数量减去一个。如果你有超过n个线程,那么至少有两个线程在处理CPU时间,这使得它们都变慢了!
  • 工作线程什么也不做,只是坐在一个循环中,让工作从队列中完成并完成工作。
  • 如果队列为空,则“取出工作”阻止
  • 当新作品到达时,其中一个被阻止的线程将被重新激活。

如何使用这些属性构建队列是一个着名的问题,称为生产者/消费者问题。关于如何执行阻塞生产者 - 消费者队列的任何许多实现,有很多文章。我建议找一个现有的调试版,而不是试着写自己的;做得对可能很棘手。

答案 1 :(得分:3)

睡眠的分辨率由当前的计时器滴答间隔决定,通常为10或15毫秒,具体取决于Windows的版本。但是,可以通过发出timeBeginPeriod命令来更改此设置。请参阅this answer

答案 2 :(得分:3)

Windows不是RTOS(实时操作系统),因此您无法准确确定线程何时恢复。 Thread.Sleep(5)真的意味着“在5毫秒之后叫醒我”。实际的休眠时间由特定硬件决定,主要由系统负载决定。您可以尝试running your application on a higher priority解决system load问题。

顺便说一句,System.Threading.Timer是一种更好的方法(尽管评论仍然适用)。

答案 3 :(得分:1)

检查计时器的实际频率:许多硬件计时器具有实际分辨率

  65536 ticks per hour = 65536 / 3600 = 18.204 ticks per second 

所谓的“18.2”常数,这就是实际计时器的分辨率 1 / 18.2 = 55 ms 的原因;在Sleep(5)的情况下,这意味着可能是Sleep(0)Sleep(55),具体取决于整理。

答案 4 :(得分:1)

不确定这是最好的方法,而是另一种方法 尝试BlockingCollection,你在制作人中所做的只是添加和睡眠 如果需要,消费者可以选择全职工作 这仍然无法解释为什么更高功率的PC运行更少的周期。

答案 5 :(得分:1)

你可以平均每秒运行200次 吗?

var delay = TimeSpan.FromMillseconds(5);
while (process_data) {
    Console.WriteLine("do work");
    var now = DateTime.Now;
    if (now < nextDue) 
        System.Threading.Thread.Sleep(nextDue - now);
    nextDue = nextDue.Add(delay);
}

使用这种技术,你的循环会有点磕磕绊绊,但平均来说应该没问题,因为代码既不依赖Sleep的分辨率也不依赖于DateTime.Now的分辨率。

您甚至可以将此方法与计时器结合使用。