跨平台的C++睡眠函数

48

使用宏定义能否实现跨平台的"Sleep"代码?比如:

#ifdef LINUX
#include <header_for_linux_sleep_function.h>
#endif
#ifdef WINDOWS
#include <header_for_windows_sleep_function.h>
#endif
...
Sleep(miliseconds);
...

如果您不介意处理器的运转声并且拥有C++11,您可以使用 <chrono> - chris
15
为什么要让处理器一直运转?如果你使用的是C++11,你可以使用类似于std::this_thread::sleep_for(std::chrono::milliseconds(n))的方法,它不会消耗任何CPU。 - R. Martinho Fernandes
5
@KamilKrzyszczuk 这几乎是一个毫无价值的描述。我怀疑不存在很多“纯C++”代码,因为没有任何现有编译器可以处理“纯C++”。就这个问题而言,C++11 不是一个扩展,它实际上是真正的“纯C++”。 - R. Martinho Fernandes
@R.MartinhoFernandes,我从来没有意识到这个存在;我昨天才开始使用chrono。这节省了我很多麻烦,谢谢。 - chris
在我的程序中,我使用 <time.h>。它非常可靠。 - Rontogiannis Aristofanis
7个回答

83

是的,但这仅适用于 C++11更新版本

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

其中ms是您想要以毫秒为单位休眠的时间量。

您还可以将milliseconds替换为nanosecondsmicrosecondssecondsminuteshours。(这些是类型std::chrono::duration的特化)。

更新:C++14中,如果您要休眠一段固定的时间,例如100毫秒,std::chrono::milliseconds(100)可以写成100ms。这是由于用户定义字面量的引入,这是在C++11中引入的。在C++14中,chrono库已扩展以包括以下用户定义字面量:

这意味着您可以编写以下内容:

#include <chrono>
#include <thread>
using namespace std::literals::chrono_literals;

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

请注意,尽管使用using namespace std::literals::chrono_literals提供了最少量的命名空间污染,但这些运算符也在using namespace std::literalsusing namespace std::chrono中可用。


@ThePirate42 哈哈谢谢。不过当时发布的时候,大多数人还没有开始使用C++11,所以被接受的答案更具有普遍性。 - Michael Dorst

47

有的。你需要将不同的系统休眠调用和包含语句放在你自己的函数中,就像下面这样:

#ifdef LINUX
#include <unistd.h>
#endif
#ifdef WINDOWS
#include <windows.h>
#endif

void mySleep(int sleepMs)
{
#ifdef LINUX
    usleep(sleepMs * 1000);   // usleep takes sleep time in us (1 millionth of a second)
#endif
#ifdef WINDOWS
    Sleep(sleepMs);
#endif
}

然后您的代码调用 mySleep 来睡眠,而不是直接进行系统调用。


7
#ifdef LINUX int Sleep(int sleepMs) { return usleep(sleepMs * 1000); } #endif如果是LINUX系统,则定义一个名为Sleep的函数,输入参数为毫秒数sleepMs,返回值为微秒数(sleepMs乘以1000)经过usleep处理后的结果。 - Joshua
那么为什么上面的代码输出是许多个1字符而不是只有一个呢?我知道这与问题无关。但是如何修复它? - ElSajko
1
@KamilKrzyszczuk:因为你犯了其他错误。你发布的代码应该每秒打印一个“1”字符。 - Mooing Duck
3
为什么使用 int 来表示 mySleep?使用 unsigned int 是否更合适呢?毕竟,你不可能睡负数秒! :P - Sebastian Lenartowicz
宏无法正常工作。请参考以下链接,了解如何可靠地检测平台:https://dev59.com/jW025IYBdhLWcg3wl3Am - Danvil
显示剩余5条评论

29

shf301有一个好主意,但是这种方式更好:

#ifdef _WINDOWS
#include <windows.h>
#else
#include <unistd.h>
#define Sleep(x) usleep((x)*1000)
#endif

然后像这样使用:

Sleep(how_many_milliseconds);

1
方便!谢谢! :) - cmcromance

19

获取 Boost

#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
...
boost::this_thread::sleep(boost::posix_time::millisec(milliseconds));

9
现在这是C++11的内容。然而,posix_time被称为chrono - Michael Dorst

8
股票方案是select()调用(需要Winsock)。这个特定的调用在Linux和Windows上的行为完全相同。
long value; /* time in microseconds */

struct timeval tv;
tv.tv_sec = value / 1000000;
tv.tv_usec = value % 1000000;
select(0, NULL, NULL, NULL, &tf);

有趣的解决方案,但我更喜欢你对shf301回答的评论。 - Mooing Duck
这在Windows上不起作用,无论请求的超时时间如何,它都会立即返回。 - foddex

1
在Linux中,请记住usleep有一个限制。 你不能让程序'睡眠'超过1000秒。
我会这样写
struct timespec req={0},rem={0};
req.tv_sec=(milisec/1000);
req.tv_nsec=(milisec - req.tv_sec*1000)*1000000;
nanosleep(&req,&rem);

1
自从C++11以来,您可以这样做。
#include<chrono>
#include<thread>
int main(){
    std::this_thread::sleep_for(std::chrono::milliseconds(x));//sleeps for x milliseconds
    std::this_thread::sleep_for(std::chrono::seconds(x));//sleeps for x seconds  
    std::this_thread::sleep_for(std::chrono::minutes(x));//sleeps for x minutes
    std::this_thread::sleep_for(std::chrono::hours(x));//sleeps for x hours.
  return 0;  
}

我不知道为什么你想使用混乱的宏,当你可以使用这种方法。这种方法很棒,跨平台,并且包含在C++标准中。

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