毫秒级睡眠

842

我知道 POSIX sleep(x) 函数可以让程序休眠 x 秒。那么在 C++ 中是否有函数可以让程序休眠 x 毫秒 呢?


10
你应该知道,在Windows中,Sleep()函数具有毫秒级的精度,但它的准确性可以高达数个数量级。你可能认为你要睡眠4毫秒,但实际上会睡眠400毫秒。 - John Dibling
5
我认为他正在使用 POSIX 的 sleep,而不是 Win32 的 Sleep,因为他提到了“x秒”。 - CB Bailey
1
虽然C和C++有不同的名称修饰,这可能是错误和不兼容性的源头,但在大多数情况下,在C++中使用C头文件是可以的。然而,如果您想绝对确保没有任何问题,可以将C头文件包含在extern "C" {}块内。此外,如果您在同一项目中拥有C和C++源文件,强烈建议您这样做以避免任何问题,特别是如果您在两种类型的源文件中都包含相同的头文件(在这种情况下,这是必要的)。如果您有一个纯C++项目,它可能会毫无问题地工作。 - notadam
4
不是400毫秒,你可能曾经获得的最差精度来自Windows 9x,其GetTickCount具有55毫秒的分辨率;后续版本的分辨率为16毫秒或更低。一位用户认为他从Sleep函数中获得了16毫秒的分辨率,但随后报告称Sleep本身相当准确,表面上的不精确是由于使用GetTickCount来测量时间的流逝所造成的。 - Qwertie
我刚落入了Windows 10中的MS陷阱。 使用QueryPerformanceCounter后,Sleep(1)大约在14毫秒后返回。 - Günter
在符合 POSIX 标准的平台上可以使用 usleep() - Jesper Juhl
20个回答

1692

在C++11中,您可以使用标准库设施来实现此目的:

#include <chrono>
#include <thread>
std::this_thread::sleep_for(std::chrono::milliseconds(x));

清晰易读,不再需要猜测 sleep() 函数使用的单位。


98
这是正确的做法。就这样。线程和计时器跨平台。 - Void
126
一种非常好的方法,但“the”和“period”是非常强烈的词语。 - Mad Physicist
11
这是需要翻译的内容: Is it a busy sleep? I need to yield to another thread during sleep; can I use sleep_for for that?这是翻译的结果: 这是一个忙碌的睡眠吗?我需要在睡眠期间让出给另一个线程;我可以使用 sleep_for 吗? - Michael
25
@Michael:这不是繁忙的休眠,它会让出给其他线程。 - HighCommander4
8
我的理由是,“这是正确的方法,没有其他选择”。这是一个绝对陈述,意味着A)存在一种“正确”的方法适用于所有情况,B)在某些情况下不存在等同于“正确”的其他方法。我从未暗示过我认为答案中的解决方案不足以解决问题:“确实是非常好的方法”是我描述它的方式。我的反对意见是对绝对语句的使用。存在其他可能的好的解决方案,暗示否则似乎是不合理的,因此发表了这个评论。 - Mad Physicist
显示剩余19条评论

524

请注意,没有标准的C API可用于毫秒级操作,因此(在Unix系统中),您需要使用接受微秒参数的usleep函数:

#include <unistd.h>

unsigned int microseconds;
...
usleep(microseconds);

3
这是一个繁忙的睡眠吗?我需要在睡眠期间让出给另一个线程;我能使用 usleep 吗? - Michael
16
这不是忙等待 https://dev59.com/UWsz5IYBdhLWcg3wBzfi#8156644,`nanosleep`可能是更好的选择,因为`usleep`已经过时。 - jswetzen
5
Niet,请考虑提及@HighCommander4的答案,如果您有C++11编译器,那么它更具可移植性。 - einpoklum
10
usleep() 函数在 POSIX 标准中于 2001 年被弃用,并于 2008 年被移除。 - Jetski S-type

86

为保持可移植性,您可以使用Boost::Thread来进行休眠:

#include <boost/thread/thread.hpp>

int main()
{
    //waits 2 seconds
    boost::this_thread::sleep( boost::posix_time::seconds(1) );
    boost::this_thread::sleep( boost::posix_time::milliseconds(1000) );

    return 0;
}

这个答案是一个重复的,已经在这个问题中发布过。也许你可以在那里找到一些可用的答案。


6
请记住,在多线程环境中,boost::this_thread::sleep 会向您的代码添加一个中断点。 - Martin Meeser

43
在Unix中,您可以使用usleep函数。 在Windows中则有Sleep函数。

7
Windows函数的调用时间以毫秒为单位。 - shindigo
20
分别需要包含 <unistd.h> 或 <Windows.h>。 - gbmhunter
是的,但实际时间分辨率可能是15-16毫秒(即使调用中的单位为1毫秒),因此最小时间可能是15-16毫秒? - Peter Mortensen

33

根据您所使用的平台,您可能拥有usleepnanosleepusleep已弃用并已从最新的POSIX标准中删除;nanosleep更受推荐。


6
请注意,虽然 <unistd.h> 中声明了 usleep() 函数,但令人困惑的是 nanosleep() 函数却在 <time.h>/<ctime> 中声明。 - gbmhunter

32

使用C++14中的std和数字字面量:

#include <chrono>
#include <thread>

using namespace std::chrono_literals;

std::this_thread::sleep_for(123ms);

3
这是如何实现的?123ms 看起来有点奇怪。 - vy32
3
简言之,它被实现为用户定义的字面值,类似于您定义其他运算符:long double operator "" ms(long double)在我看来,这比 chrono::milliseconds(1000) 更易读。 有关更多信息,请参见用户定义的字面值 - Martin Flaska

30
#include <chrono>
#include <thread>

std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // sleep for 1 second

记得导入这两个头文件。


14
这只是重复了HighCommander4的回答。你应该直接点赞已有的回答,而不是再次写同样的内容。 - Toby Speight

29

为什么不使用time.h库?它可以在Windows和POSIX系统上运行(请勿在生产中使用此代码!):

CPU保持空闲状态:

#include <iostream>
#ifdef _WIN32
    #include <windows.h>
#else
    #include <unistd.h>
#endif // _WIN32

using namespace std;

void sleepcp(int milliseconds);

void sleepcp(int milliseconds) // Cross-platform sleep function
{
    #ifdef _WIN32
        Sleep(milliseconds);
    #else
        usleep(milliseconds * 1000);
    #endif // _WIN32
}
int main()
{
    cout << "Hi! At the count to 3, I'll die! :)" << endl;
    sleepcp(3000);
    cout << "urrrrggghhhh!" << endl;
}

34
那段代码的一个问题是它是一个繁忙循环,它将继续使用单个处理器核心的100%。sleep函数是围绕一个操作系统调用实现的,该调用会使当前线程进入睡眠状态并执行其他操作,并且仅在指定时间到期时唤醒线程。 - Ismael
你说得对 - 它将会占用一个CPU核心的100%。所以这里是使用系统休眠函数重写的代码 - 而且它仍然是跨平台的: - Bart Grzybicki
@BartGrzybicki 我知道这是一个旧答案,但在 Windows 机器上的 Visual Studio 2017 中,默认情况下 #ifdef WIN32 不会被评估为真。 - kayleeFrye_onDeck
2
@kayleeFrye_onDeck 代码有误。应该是 #ifdef _WIN32 - Contango
1
@Contango 我知道啊!但是我写那篇文章的时候不知道啊...哈哈。感谢你的跟进! - kayleeFrye_onDeck

18

nanosleepusleep 更好 - 它对中断更具韧性。


7
我熟悉 usleep,但不熟悉 nanosleep。请提供在Linux上使用它的示例。 在Linux上使用 nanosleep 的示例代码如下: - jww

18
#include <windows.h>

语法:

Sleep (  __in DWORD dwMilliseconds   );

使用方法:

Sleep (1000); //Sleeps for 1000 ms or 1 sec

4
需要包括什么内容? - ʇolɐǝz ǝɥʇ qoq
#include <WinBase.h> - foobar
10
不需要,你需要#include <windows.h> - ʇolɐǝz ǝɥʇ qoq
10
问题强烈暗示需要一个符合POSIX标准的解决方案。 - Toby Speight

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接