Сон протягом мілісекунд


630

Я знаю, що sleep(x)функція POSIX змушує програму спати протягом x секунд. Чи є функція змусити програму спати протягом x мілісекунд у С ++?


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сам по собі був досить точним, і очевидна неточність була викликана використанням GetTickCountвимірювання часу.
Qwertie

Відповіді:


457

Зауважте, що не існує стандартного API 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

1270

У C ++ 11 це можна зробити за допомогою стандартних засобів бібліотеки:

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

Чіткий і читабельний, більше не потрібно здогадуватися, які одиниці sleep()займає функція.


6
Чи визначає std :: this_thread :: sleep_for точку переривання? Як boost :: this_thread_sleep робить?
Мартін Мізер

73
Це правильний спосіб зробити це. Період. Нитка - це поперечна платформа, а також хроно.
Недійсна

88
@Void. Дуже хороший спосіб, звичайно, але "" і "період" - це жахливо сильні слова.
Божевільний фізик

5
Це зайнятий сон? Мені потрібно під час сну поступатися іншій нитці; чи можу я використовувати sleep_forдля цього?
Майкл

14
@Michael: Це не зайнятий сон, він поступатиметься іншим темам.
HighCommander4

83

Щоб залишатися портативними, ви можете використовувати Boost :: Нитка для сну:

#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додає точку переривання до вашого коду. boost.org/doc/libs/1_49_0/doc/html/thread/…
Мартін Мізер

35

В Unix ви можете використовувати usleep .

У Windows є сон .


4
і виклик Windows знаходиться в мілісекундах.
шиндиго

17
Ви повинні включити <unistd.h> або <Windows.h> відповідно.
gbmhunter

Так, але чи не могло фактичне дозвіл часу бути 15-16 мс (навіть якщо одиниця дзвінка становить 1 мс), і, таким чином, мінімальний час становитиме 15-16 мс?
Пітер Мортенсен

33

Залежно від вашої платформи ви можете мати usleepабо nanosleepнаявну. usleepзастаріла і видалена з останнього стандарту POSIX; nanosleepє кращим.


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% одного ядра процесора. Функція сну реалізується навколо виклику ОС, який увімкне сплячий поточний потік і зробить щось інше, і прокине потік лише тоді, коли зазначений час закінчиться.
Ісмаїл

Ви маєте рацію - він буде споживати 100% одного центрального процесора. Тож ось переписаний код за допомогою функцій системного сну - і це все ще кросплатформний:
Барт Гжибицький

@BartGrzybicki Я знаю, що це стара відповідь, і все, але в Visual Studio 2017 на машині Windows, #ifdef WIN32не оцінюється як істинна за замовчуванням.
kayleeFrye_onDeck

2
@kayleeFrye_onDeck Код невірний. Це повинно бути #ifdef _WIN32.
Контанго

1
@Contango Я це знав! Але не тоді, коли я це написав ... lol. Дякуємо за подальші дії!
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

3
Що для цього потрібно включити?
ʇolɐǝz ǝɥʇ qoq

#include <WinBase.h>
foobar

7
Ні, вам потрібно#include <windows.h>
ʇolɐǝz ǝɥʇ qoq

7
Питання напевно означає, що потрібне рішення POSIX.
Toby Speight

7

Якщо ви використовуєте MS Visual C ++ 10.0, це можна зробити за допомогою стандартних засобів бібліотеки:

Concurrency::wait(milliseconds);

Ви будете потребувати:

#include <concrt.h>

10
Не використовуйте слово "стандарт", коли ви насправді цього не маєте на увазі. <concrt.h>це НЕ заголовок Стандартна бібліотека - це може бути бібліотека платформи; у такому випадку слід чітко викласти передумови.
Toby Speight

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 мс в деяких випадках? Наприклад, якщо ви використовуєте режим сну (3), він насправді буде спати протягом 3 мс, чи замість цього буде 15-16 мс?
Пітер Мортенсен

3

Вибір дзвінка - це спосіб більшої точності (час сну можна вказати в наносекундах).


Хоча це може бути цінним підказом для вирішення проблеми, хороша відповідь також демонструє рішення. Будь ласка редагувати надати приклад коду , щоб показати , що ви маєте в виду. Крім того, розгляньте, як написати це замість цього.
Toby Speight

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
}

Віддає перевагу , nanosleep()щоб usleep(): останній застарів і був видалений з самого останнього стандарту POSIX.
Toby Speight
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.