Спать в течение миллисекунд

632

Я знаю, что sleep(x)функция POSIX переводит программу в спящий режим на х секунд. Есть ли функция, чтобы заставить программу спать на х миллисекунд в C ++?

Прасант Мадхаван
источник
7
Вы должны знать, что в любом случае в Windows точностьSleep() составляет миллисекунды , но ее точность может быть на несколько порядков выше. Вы можете думать, что вы спите в течение 4 миллисекунд, но на самом деле вы спите в течение 400.
Джон Диблинг
5
@John Dibling: я думаю, что он использует POSIX sleep, а не win32, Sleepучитывая "х секунд".
CB Bailey
1
Хотя C и C ++ имеют различное искажение имен, которое может быть источником ошибок и несовместимости, в большинстве случаев нормально использовать заголовки C в C ++. Однако, если вы хотите быть абсолютно уверены, что ничего не идет не так, #includeиспользуйте заголовок C внутри extern "C" {}блока. Кроме того, если у вас есть исходные файлы C и C ++ в одном и том же проекте, настоятельно рекомендуется сделать это, чтобы избежать каких-либо проблем, особенно если вы включаете одинаковые заголовки в исходные файлы обоих типов (в этом случае это необходимо) , Если у вас есть чисто C ++ проект, он может просто работать без проблем.
adam10603
2
@JohnDibling нет, не 400мс. Худшая точность, которую вы когда-либо получали, была от Windows 9x, GetTickCountразрешение которой составляло 55 мс; более поздние версии имели разрешение 16 мс или меньше. Один пользователь думал, что он получал разрешение 16 мс от Sleep, но затем сообщил, что Sleepсам по себе он был довольно точным, и очевидная неточность была вызвана использованием GetTickCountизмерения времени.
Qwertie

Ответы:

457

Обратите внимание, что стандартного C API для миллисекунд не существует, поэтому (в Unix) вам придется согласиться usleep, что принимает микросекунды:

#include <unistd.h>

unsigned int microseconds;
...
usleep(microseconds);
Нит Тёмный Абсол
источник
2
Это занятый сон? Мне нужно уступить другому потоку во время сна; я могу использовать usleepдля этого?
Майкл
13
Это не занятое ожидание stackoverflow.com/a/8156644/1206499 и nanosleepможет быть лучшим выбором, поскольку usleepоно устарело.
Jswetzen
4
Нет, пожалуйста, рассмотрите возможность упомянуть ответ @ HighCommander4, который более переносим, ​​если у вас есть компилятор C ++ 11.
einpoklum
6
usleep () устарела в POSIX в 2001 году и удалена в 2008 году.
Jetski S-type
1271

В C ++ 11 вы можете сделать это с помощью стандартных библиотек:

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

Понятно и читабельно, больше не нужно угадывать, в каких единицах sleep()принимает функция.

HighCommander4
источник
6
Определяет ли std :: this_thread :: sleep_for точку прерывания? Как boost :: this_thread_sleep делает?
Мартин Мизер
73
Это правильный способ сделать это. Период. Нить кроссплатформенная, а также хроно.
Пустота
88
@Void. Очень хороший путь, конечно, но «и» - очень сильные слова.
Безумный физик
5
Это занятый сон? Мне нужно уступить другому потоку во время сна; я могу использовать sleep_forдля этого?
Майкл
14
@Michael: Это не занятой сон, он уступит другим потокам.
HighCommander4
83

Чтобы оставаться портативным, вы можете использовать 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;
}

Этот ответ является дубликатом и был опубликован в этом вопросе ранее. Возможно, вы могли бы найти некоторые полезные ответы там тоже.

MOnsDaR
источник
6
Имейте в виду, что - в многопоточной среде - boost::this_thread::sleepдобавляет точку прерывания в ваш код. boost.org/doc/libs/1_49_0/doc/html/thread/…
Мартин Мизер
35

В Unix вы можете использовать usleep .

В винде есть Sleep .

INS
источник
4
и вызов Windows в миллисекундах.
Shindigo
17
Вы должны включить <unistd.h> или <Windows.h> соответственно.
gbmhunter
Да, но не может ли фактическое разрешение по времени составлять 15-16 мс (даже если единица измерения в вызове составляет 1 мс) и, следовательно, минимальное время составляет 15-16 мс?
Питер Мортенсен
33

В зависимости от вашей платформы вы можете иметь usleepили nanosleepдоступны. usleepустарела и была удалена из самого последнего стандарта POSIX; nanosleepявляется предпочтительным.

CB Bailey
источник
6
Обратите внимание, что, хотя usleep()объявляется в <unistd.h>, сбивает с толку, nanosleep()объявляется в <time.h>/ <ctime>.
gbmhunter
27

Почему бы не использовать библиотеку time.h? Работает в системах Windows и POSIX:

#include <iostream>
#include <time.h>

using namespace std;

void sleepcp(int milliseconds);

void sleepcp(int milliseconds) // Cross-platform sleep function
{
    clock_t time_end;
    time_end = clock() + milliseconds * CLOCKS_PER_SEC/1000;
    while (clock() < time_end)
    {
    }
}
int main()
{
    cout << "Hi! At the count to 3, I'll die! :)" << endl;
    sleepcp(3000);
    cout << "urrrrggghhhh!" << endl;
}

Исправленный код - теперь процессор остается в состоянии IDLE [2014.05.24]:

#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;
}
Барт Грзибицкий
источник
24
Одна из проблем с этим кодом заключается в том, что это занятый цикл, он будет продолжать использовать 100% одноядерного ядра. Функция sleep реализована вокруг вызова ОС, который переводит текущий поток в спящий режим и делает что-то еще, и активирует поток только по истечении указанного времени.
Исмаэль
Вы правы - он будет потреблять 100% одного ядра процессора. Итак, вот переписанный код с использованием системных спящих функций - и он все еще кроссплатформенный:
Барт Грзибицкий,
@BartGrzybicki Я знаю, что это старый ответ и все, но в Visual Studio 2017 на компьютере с Windows #ifdef WIN32не оценивается как true по умолчанию.
kayleeFrye_onDeck
2
@kayleeFrye_onDeck Код неправильный. Так и должно быть #ifdef _WIN32.
контанго
1
@Контанго, я знал это! Но не тогда, когда я это написал ... лол. Спасибо за продолжение!
kayleeFrye_onDeck
17

nanosleepэто лучший выбор, чем usleep- он более устойчив к прерываниям.

Йохан Котлински
источник
6
Я был знаком с usleep, но нет nanosleep. Вы должны предоставить пример использования его в Linux.
jww
14
#include <windows.h>

Синтаксис:

Sleep (  __in DWORD dwMilliseconds   );

Применение:

Sleep (1000); //Sleeps for 1000 ms or 1 sec
Foobar
источник
3
Что для этого нужно включить?
ʇolɐǝz ǝɥʇ qoq
#include <WinBase.h>
Foobar
7
Нет, вам нужно#include <windows.h>
ʇolɐǝz ǝɥʇ qoq
7
Этот вопрос строго подразумевает, что требуется решение POSIX.
Тоби Спейт
7

Если вы используете MS Visual C ++ 10.0, вы можете сделать это с помощью стандартных библиотек:

Concurrency::wait(milliseconds);

тебе понадобится:

#include <concrt.h>
метронит
источник
10
Не используйте слово «стандарт», если вы на самом деле не имеете это в виду. <concrt.h>это не заголовок Стандартная библиотека - это может быть библиотека платформы; в этом случае вы должны четко сформулировать предпосылки.
Тоби Спейт
5

На платформах с этой selectфункцией (POSIX, Linux и Windows) вы можете сделать:

void sleep(unsigned long msec) {
    timeval delay = {msec / 1000, msec % 1000 * 1000};
    int rc = ::select(0, NULL, NULL, NULL, &delay);
    if(-1 == rc) {
        // Handle signals by continuing to sleep or return immediately.
    }
}

Однако в настоящее время есть лучшие альтернативы.

Максим Егорушкин
источник
Невозможно скомпилировать в VS2017 на компьютере с Windows:error LNK2019: unresolved external symbol _select@20 referenced in function "void __cdecl sleep(unsigned long)" (?sleep@@YAXK@Z)
kayleeFrye_onDeck
@kayleeFrye_onDeck Это компилируется. Просто не связывает. Поиск ваших документов Windows.
Максим Егорушкин
какой заголовок вы используете для timeval ??
Тотте Карлссон
@TotteKarlsson <sys/time.h>.
Максим Егорушкин
4

Способ сна вашей программы на C ++ - это Sleep(int)метод. Заголовочный файл для него#include "windows.h."

Например:

#include "stdafx.h"
#include "windows.h"
#include "iostream"
using namespace std;

int main()
{
    int x = 6000;
    Sleep(x);
    cout << "6 seconds have passed" << endl;
    return 0;
}

Время, в течение которого он спит, измеряется в миллисекундах и не имеет ограничений.

Second = 1000 milliseconds
Minute = 60000 milliseconds
Hour = 3600000 milliseconds
фита
источник
3
Что вы имеете в виду, что нет предела? Это, безусловно, имеет предел, который составляет 0xFFFFFFFE. Ожидание 0xFFFFFFFF просто не истечет (это означает, что оно будет ждать окончания программы).
Иззи
Я не это имел ввиду, Иззи, извини за наше недопонимание. Я имел в виду, что вы можете ввести любое положительное число миллисекунд. Так что будет ждать столько миллисекунд, чтобы закрыть программу. Если вы не понимаете, скажите, пожалуйста, я объясню вам больше.
Пх
Да, но каково его фактическое разрешение по времени? Разве это не может быть 15-16 мс в некоторых случаях? Например, если вы используете Sleep (3), он будет фактически спать в течение 3 мс или вместо этого будет 15-16 мс?
Питер Мортенсен
3

Вызов select - способ повысить точность (время ожидания может быть указано в наносекундах).

Мадхава Гайквад
источник
Хотя это может быть ценным советом для решения проблемы, хороший ответ также демонстрирует решение. Пожалуйста, измените, чтобы предоставить пример кода, чтобы показать, что вы имеете в виду. В качестве альтернативы, попробуйте написать это как комментарий.
Тоби Спейт
3

Используйте Boost асинхронные потоки ввода / вывода, спите в течение x миллисекунд;

#include <boost/thread.hpp>
#include <boost/asio.hpp>

boost::thread::sleep(boost::get_system_time() + boost::posix_time::millisec(1000));
Анум Шераз
источник
Что на самом деле произойдет, если вы попытаетесь уснуть в течение 3 миллисекунд? Это будет 15-16 миллисекунд вместо этого? Вы измерили это?
Питер Мортенсен
1

Вопрос старый, но мне удалось найти простой способ добавить это в мое приложение. Вы можете создать макрос C / C ++, как показано ниже, используя его:

#ifndef MACROS_H
#define MACROS_H

#include <unistd.h>

#define msleep(X) usleep(X * 1000)

#endif // MACROS_H
ВПЗ
источник
1

Из C ++ 14 с использованием std, а также его числовых литералов:

#include <chrono>
#include <thread>

using namespace std::chrono;

std::this_thread::sleep_for(123ms);
Мартин Фласка
источник
0

В качестве замены Win32 для систем POSIX:

void Sleep(unsigned int milliseconds) {
    usleep(milliseconds * 1000);
}

while (1) {
    printf(".");
    Sleep((unsigned int)(1000.0f/20.0f)); // 20 fps
}
lama12345
источник
Предпочитает , nanosleep()чтобы usleep(): последний устарел и был удален из самого последнего стандарта POSIX.
Тоби Спейт