在C ++中经过30ms的时间之后退出循环的最佳方法是什么

时间:2009-06-03 17:51:07

标签: c++ qt timer clock

在C ++中尽可能接近30ms退出循环的最佳方法是什么。轮询提升:microsec_clock?轮询QTime?还有别的吗?

类似的东西:

A = now;
for (blah; blah; blah) {
    Blah();
    if (now - A > 30000)
         break;
}

它应该适用于Linux,OS X和Windows。

循环中的计算用于更新模拟。每隔30ms,我想更新视口。

9 个答案:

答案 0 :(得分:10)

  

循环中的计算是为了   更新模拟。每隔30ms,我会   喜欢更新视口。

您是否考虑过使用线程?您描述的内容似乎是您应该使用线程而不是计时器的完美示例。

主进程线程不断处理UI,并将QTimer设置为30ms以进行更新。它锁定QMutex以访问数据,执行更新并释放互斥锁。

第二个线程(参见QThread)进行模拟。对于每个循环,它会锁定QMutex,进行计算并在数据处于稳定状态时释放互斥锁(适用于UI更新)。

随着多核处理器的增长趋势,你应该越来越多地考虑使用线程而不是使用定时器。您的应用程序自动受益于新处理器的增加功率(多核)。

答案 1 :(得分:4)

虽然这不能回答这个问题,但它可能会再次考虑解决方案。将模拟代码和用户界面放在不同的线程中怎么样?如果您使用Qt,可以使用计时器甚至QThread::msleep()来实现定期更新。您可以调整threaded Mandelbrot example以满足您的需求。

答案 2 :(得分:2)

此链接中的代码段示例几乎可以满足您的需求:

http://www.cplusplus.com/reference/clibrary/ctime/clock/

改编自他们的例子:

void runwait ( int seconds )
{
   clock_t endwait;
   endwait = clock () + seconds * CLOCKS_PER_SEC ;
   while (clock() < endwait)
   {
      /* Do stuff while waiting */
   }
}

答案 3 :(得分:2)

简短的回答是:一般情况下你不能,但如果你在正确的操作系统或正确的硬件上运行,你就可以。

使用英特尔系统上的汇编调用以及其他架构上的其他内容,您可以在所有操作系统上接近30毫秒。我会挖掘引用并编辑答案,以便在找到代码时包含代码。

问题在于时间切片算法以及您在多任务操作系统上的时间片结束的接近程度。

在某些实时操作系统中,您可以在系统库中进行系统调用,但我不确定该调用是什么。

编辑:哈哈!有人已在SO上发布了一个类似的片段:Timer function to provide time in nano seconds using C++

VonC已经收到了关于CPU计时器汇编代码的评论。

答案 4 :(得分:2)

如果您需要在某段时间之前完成工作,那么docflabby's answer就会出现。但是,如果您只需要等待,什么都不做,直到指定的时间过去,那么您应该使用usleep()

答案 5 :(得分:2)

根据您的问题,您需要每30ms更新一次视口。我写了一个类似的应用程序,每500毫秒探测硬件类似的东西。虽然这不能直接回答您的问题,但我有以下后续内容:

  • 你确定用于更新视口的Blah()可以在每个实例中在不到30ms的时间内执行吗?
  • 似乎更像是通过计时器回调来更好地运行Blah()。
  • 很难找到一个库定时器对象,该对象将以30ms的间隔推进以在图形框架中进行更新。在Windows XP上,我发现即使在2GHz P4上,在定时器间隔到期时推送窗口消息的标准Win32 API定时器也无法以超过300ms的间隔进行更新,无论我将定时间隔设置为多少。计时器。虽然Win32 API中有高性能计时器,但它们有许多限制,即您不能像上面引用的那样在循环中执行任何IPC(如更新UI小部件)。
  • 基本上,结果是您必须非常仔细地计划您希望如何进行更新。您可能需要使用线程,并查看您希望如何更新视口。

只需要考虑一些事情。当我参与我的项目时,他们让我感到惊讶。如果您已经考虑过这些事情,请忽略我的答案:0)。

答案 6 :(得分:2)

您可以考虑每N个模拟步骤更新视口,而不是每K毫秒更新一次。如果这是(比方说)一个严肃的商业应用程序,那么你可能会想要去其他地方建议的多线程路线,但是如果(比方说)它是为了个人或有限的观众使用以及你真正感兴趣的是你正在模拟的任何细节,然后每N步都是简单,便携,并且很可能足以让你继续使用。

答案 7 :(得分:0)

请参阅QueryPerformanceCounter和QueryPerformanceFrequency

答案 8 :(得分:0)

如果您使用的是Qt,这是一种简单的方法:

QTimer* t = new QTimer( parent ) ;
t->setInterval( 30 ) ; // in msec
t->setSingleShot( false ) ;
connect( t, SIGNAL( timeout() ), viewPort, SLOT( redraw() ) ) ;

您需要指定viewPortredraw()。然后使用t->start()启动计时器。