c# - 使用thread.sleep()使我的周期运行几百次



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

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

当我在笔记本(一个核心i5)处理器上运行此应用程序时,该周期每秒运行200-205次 - 一种预期的(如果您不考虑为什么它运行的每秒超过200倍以上))。

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

我的问题是:

  • 为什么会发生这种情况?

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

  • 是否有更好的解决方案来运行每秒200-1000次的周期?我现在正在考虑删除thread.sleep()(我在这里使用它的方式受到了很多批评)。对于12个核心,我仅在此周期中使用一个核心就没有问题。但是我对这种解决方案有一些缺点?

谢谢您的想法。

您所采用的方法根本是断裂的。一般而言,投票策略是一种不好的方法,除了"我想让其余的时间恢复到操作系统"之外,任何其他原因,您都可能做错了。p>解决问题的更好方法是:

  • 将无处理作品的线程列为螺纹范围
  • 制作一个将新作品排在队列中的线程
  • 使n个线程从队列中锻炼并进行工作。 n应该是您的CPU数量。
  • 工人线程除了坐在循环中,从队列中锻炼并完成工作。
  • 如果队列为空,则"删除"
  • 当新作品到达时,一个被阻塞的线程被重新激活。

如何使用这些属性建立队列是一个著名的问题,称为生产者/消费者问题。关于如何执行任何阻止生产者 - 消费者队列的实现,有很多文章。我建议找到一个现有的调试,而不是试图编写自己的调试;正确正确可能很棘手。

Windows不是RTO(实时操作系统),因此您无法精确确定线程何时恢复。Thread.Sleep(5)确实意味着"不久就将我唤醒5ms"。实际的睡眠时间由特定的硬件决定,主要由系统负载决定。您可以通过更高的优先级运行应用程序来尝试解决system load问题。

btw,system.threading.timer是一种更好的方法(上面的注释仍然适用)。

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

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

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

所谓的" 18.2"常数,这就是为什么实际计时器的分辨率为 1/18.2 = 55 ms ;对于Sleep(5),这意味着可以是Sleep(0)Sleep(55),具体取决于圆形。

不确定它是最好的方法,而是另一种方法。
尝试BlockingCollection,您在生产者中所做的就是添加和睡眠。
然后,消费者可以在需要时选择全职工作。
这仍然无法解释为什么较高功率的PC持续更少的周期。

您可以平均运行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的分辨率。

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

最新更新