Śpij przez milisekundy

630

Wiem, że sleep(x)funkcja POSIX sprawia, że ​​program śpi przez x sekund. Czy istnieje funkcja umożliwiająca uśpienie programu przez x milisekund w C ++?

Prasanth Madhavan
źródło
7
Należy pamiętać, że w Windows i tak Sleep()ma milisekundową precyzję , ale jej dokładność może być o rząd wielkości wyższa. Możesz myśleć, że śpisz przez 4 milisekundy, ale tak naprawdę śpisz przez 400.
John Dibling
5
@John Dibling: Myślę, że używa POSIX sleep, a nie Win32, Sleepbiorąc pod uwagę „x sekund”.
CB Bailey,
1
Chociaż C i C ++ mają różne zniekształcanie nazw, co może być źródłem błędów i niezgodności, w większości przypadków dobrze jest używać nagłówków C w C ++. Jeśli jednak chcesz mieć absolutną pewność, że nic nie pójdzie źle, #includenagłówek C wewnątrz extern "C" {}bloku. Ponadto, jeśli masz pliki źródłowe C i C ++ w tym samym projekcie, zdecydowanie zaleca się to zrobić, aby uniknąć problemów, zwłaszcza jeśli dołączasz te same nagłówki do obu rodzajów plików źródłowych (w takim przypadku jest to konieczne) . Jeśli masz projekt wyłącznie w języku C ++, może on po prostu działać bez problemu.
adam10603
2
@JohnDibling nie, nie 400 ms. Najgorszą precyzją, jaką mogłeś kiedykolwiek uzyskać, był system Windows 9x o GetTickCountrozdzielczości 55 ms; późniejsze wersje miały rozdzielczość 16ms lub mniejszą. Jeden z użytkowników pomyślał, że uzyskuje rozdzielczość 16ms z trybu uśpienia, ale następnie stwierdził, że Sleepsam był dość dokładny, a widoczna niedokładność była spowodowana użyciem GetTickCountdo pomiaru upływu czasu.
Qwertie,

Odpowiedzi:

457

Zauważ, że nie ma standardowego interfejsu API C dla milisekund, więc (w Uniksie) będziesz musiał się zadowolić usleep, co akceptuje mikrosekundy:

#include <unistd.h>

unsigned int microseconds;
...
usleep(microseconds);
Niet the Dark Absol
źródło
2
Czy to pracowity sen? Podczas snu muszę ustąpić kolejnemu wątkowi; czy mogę usleepdo tego użyć ?
Michael,
13
Nie jest to zajęty czekanie stackoverflow.com/a/8156644/1206499 i nanosleepmoże być lepszym wyborem, ponieważ usleepjest przestarzały.
jswetzen,
4
Nie, proszę wspomnieć o odpowiedzi @ HighCommander4, która jest bardziej przenośna, jeśli masz kompilator C ++ 11.
einpoklum
6
usleep () przestarzałe w POSIX w 2001 r. i usunięte w 2008 r.
Jetski S-type
1270

W C ++ 11 możesz to zrobić za pomocą standardowych narzędzi bibliotecznych:

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

Jasne i czytelne, nie trzeba już zgadywać, jakie jednostki sleep()przyjmuje ta funkcja.

HighCommander4
źródło
6
Czy std :: this_thread :: sleep_for definiuje punkt przerwania? Podobnie jak boost :: this_thread_sleep?
Martin Meeser,
73
To jest właściwy sposób, aby to zrobić. Kropka. Wątek jest międzyplatformowy, a także chrono.
Void
88
@Unieważnić. Z pewnością bardzo dobry sposób, ale „okres” i „okres” to strasznie mocne słowa.
Szalony fizyk
5
Czy to pracowity sen? Podczas snu muszę ustąpić kolejnemu wątkowi; czy mogę sleep_fordo tego użyć ?
Michael,
14
@Michael: To nie jest zajęty sen, ulegnie innym wątkom.
HighCommander4,
83

Aby pozostać przenośnym, możesz użyć Boost :: Thread do spania:

#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;
}

Ta odpowiedź jest duplikatem i została wcześniej opublikowana w tym pytaniu . Być może znajdziesz tam również przydatne odpowiedzi.

MOnsDaR
źródło
6
Należy pamiętać, że - w środowisku wielowątkowym - boost::this_thread::sleepdodaje punkt przerwania do kodu. boost.org/doc/libs/1_49_0/doc/html/thread/…
Martin Meeser
35

W Uniksie możesz używać usleep .

W systemie Windows jest tryb uśpienia .

INS
źródło
4
a wywołanie systemu Windows jest w milisekundach.
shindigo,
17
Musisz dołączyć odpowiednio <unistd.h> lub <Windows.h>.
gbmhunter
Tak, ale czy rzeczywista rozdzielczość czasu nie może wynosić 15-16 ms (nawet jeśli jednostka w wywołaniu wynosi 1 ms), a zatem minimalny czas powinien wynosić 15-16 ms?
Peter Mortensen,
33

W zależności od platformy możesz mieć usleeplub być nanosleepdostępny. usleepjest przestarzały i został usunięty z najnowszego standardu POSIX; nanosleepjest preferowany.

CB Bailey
źródło
6
Zauważ, że chociaż usleep()jest zadeklarowane w <unistd.h>, myląco, nanosleep()jest zadeklarowane w <time.h>/ <ctime>.
gbmhunter
27

Dlaczego nie skorzystać z biblioteki time.h? Działa w systemach Windows i 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;
}

Poprawiony kod - teraz CPU pozostaje w stanie 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;
}
Bart Grzybicki
źródło
24
Jednym z problemów związanych z tym kodem jest to, że jest to zajęta pętla, która nadal będzie wykorzystywać 100% rdzenia jednego procesora. Funkcja uśpienia jest implementowana wokół wywołania systemu operacyjnego, które uśpi bieżący wątek i zrobi coś innego, i obudzi wątek dopiero po upływie określonego czasu.
Ismael
Masz rację - pochłonie 100% jednego rdzenia procesora. Oto przepisany kod przy użyciu funkcji uśpienia systemu - i wciąż jest on wieloplatformowy:
Bart Grzybicki
@BartGrzybicki wiem, że to stara odpowiedź, ale w Visual Studio 2017 na komputerze z systemem Windows #ifdef WIN32domyślnie nie jest to prawda.
kayleeFrye_onDeck
2
@kayleeFrye_onDeck Kod jest nieprawidłowy. Powinno być #ifdef _WIN32.
Contango,
1
@Contango Wiedziałem o tym! Ale nie kiedy to napisałem ... lol. Dzięki za kontynuację!
kayleeFrye_onDeck
17

nanosleepjest lepszym wyborem niż usleep- jest bardziej odporny na zakłócenia.

Johan Kotlinski
źródło
6
Znałem się usleep, ale nie nanosleep. Powinieneś podać przykład użycia go w systemie Linux.
jww
14
#include <windows.h>

Składnia:

Sleep (  __in DWORD dwMilliseconds   );

Stosowanie:

Sleep (1000); //Sleeps for 1000 ms or 1 sec
foobar
źródło
3
Co musisz w tym uwzględnić?
ʇolɐǝz ǝɥʇ qoq
#include <WinBase.h>
foobar
7
Nie, musisz #include <windows.h>
ʇolɐǝz ǝɥʇ qoq
7
Pytanie mocno sugeruje, że wymagane jest rozwiązanie POSIX.
Toby Speight
7

Jeśli używasz MS Visual C ++ 10.0, możesz to zrobić za pomocą standardowych narzędzi bibliotecznych:

Concurrency::wait(milliseconds);

będziesz potrzebować:

#include <concrt.h>
Metronit
źródło
10
Nie używaj słowa „standard”, jeśli tak naprawdę nie masz tego na myśli. <concrt.h>to nie nagłówek Biblioteka Standard - może to być biblioteka platforma; w takim przypadku należy wyraźnie określić warunki wstępne.
Toby Speight
5

Na platformach z selectfunkcją (POSIX, Linux i Windows) możesz:

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.
    }
}

Istnieją jednak obecnie lepsze alternatywy.

Maxim Egorushkin
źródło
Wydaje się, że nie można skompilować w VS2017 na komputerze z systemem Windows:error LNK2019: unresolved external symbol _select@20 referenced in function "void __cdecl sleep(unsigned long)" (?sleep@@YAXK@Z)
kayleeFrye_onDeck
@kayleeFrye_onDeck To się kompiluje. Po prostu nie łączy. Wyszukaj dokumenty systemu Windows.
Maxim Egorushkin,
jakiego nagłówka używasz na czas?
Totte Karlsson
@TotteKarlsson <sys/time.h>.
Maxim Egorushkin
4

Sleep(int)Metodą jest sposób na uśpienie twojego programu w C ++ . Plik nagłówkowy to#include "windows.h."

Na przykład:

#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;
}

Czas snu jest mierzony w milisekundach i nie ma ograniczenia.

Second = 1000 milliseconds
Minute = 60000 milliseconds
Hour = 3600000 milliseconds
Phi
źródło
3
Co masz na myśli mówiąc, że nie ma limitu? Z pewnością ma limit, który wynosi 0xFFFFFFFE. Oczekiwanie na 0xFFFFFFFF po prostu nie przekroczy limitu czasu (co oznacza, że ​​będzie czekać do zakończenia programu).
Izzy
Nie miałem na myśli tego tak, Izzy, przepraszam za nasze nieporozumienie. Miałem na myśli, że możesz wprowadzić dowolną dodatnią liczbę milisekund. Będzie więc czekać tyle milisekund, aby zamknąć program. Jeśli nie rozumiesz, powiedz tak, wyjaśnię ci więcej.
Phi
Tak, ale jaka jest rzeczywista rozdzielczość czasowa? Czy w niektórych przypadkach nie może to być 15-16 ms? Np. Jeśli użyjesz trybu Sleep (3), czy faktycznie będzie on spał przez 3 ms, czy zamiast tego będzie miał 15-16 ms?
Peter Mortensen,
3

Wybierz połączenie jest sposobem na uzyskanie większej precyzji (czas uśpienia można określić w nanosekundach).

Madhava Gaikwad
źródło
Chociaż może to być cenna wskazówka do rozwiązania problemu, dobra odpowiedź pokazuje również rozwiązanie. Proszę edit dostarczyć przykładowy kod, aby pokazać to, co masz na myśli. Możesz też rozważyć napisanie tego jako komentarza.
Toby Speight
3

Użyj wzmocnienia asynchronicznego wątków wejścia / wyjścia, uśpienie przez x milisekund;

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

boost::thread::sleep(boost::get_system_time() + boost::posix_time::millisec(1000));
Anum Sheraz
źródło
Co się stanie, jeśli spróbujesz spać przez 3 milisekundy? Czy zamiast tego będzie to 15-16 milisekund? Zmierzyłeś to?
Peter Mortensen,
1

Pytanie jest stare, ale udało mi się znaleźć prosty sposób, aby mieć to w mojej aplikacji. Możesz utworzyć makro C / C ++, jak pokazano poniżej, użyj go:

#ifndef MACROS_H
#define MACROS_H

#include <unistd.h>

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

#endif // MACROS_H
VPZ
źródło
1

Od C ++ 14 przy użyciu std, a także jego literałów numerycznych:

#include <chrono>
#include <thread>

using namespace std::chrono;

std::this_thread::sleep_for(123ms);
Martin Flaska
źródło
0

Jako zamiennik Win32 dla systemów POSIX:

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

while (1) {
    printf(".");
    Sleep((unsigned int)(1000.0f/20.0f)); // 20 fps
}
lama12345
źródło
Wolę nanosleep()do usleep(): ta ostatnia jest nieaktualny i został usunięty z najnowszym standardem POSIX.
Toby Speight