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


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.