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

use*_*591 7 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);
}
Run Code Online (Sandbox Code Playgroud)

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

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

我的问题是:

  • 为什么会这样?

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

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

谢谢你的想法.

Eri*_*ert 6

你正在采取的方法从根本上被打破了.轮询策略通常是一种不好的方法,并且任何时候你出于"我想将剩下的时间片还给操作系统"之外的其他原因进行睡眠时,你可能做错了什么.

解决问题的更好方法是:

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

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


wdo*_*jos 3

Windows 不是 RTOS(实时操作系统),因此您无法精确确定线程何时恢复。Thread.Sleep(5)真正的意思是“不早于 5 毫秒叫醒我”。实际的睡眠时间由具体的硬件决定,并且主要由系统负载决定。您可以尝试system load通过以更高的优先级运行应用程序来解决该问题。

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