Dormez pendant des millisecondes


632

Je sais que la sleep(x)fonction POSIX fait dormir le programme pendant x secondes. Existe-t-il une fonction pour mettre le programme en veille pendant x millisecondes en C ++?


7
Vous devez savoir que, dans Windows de toute façon, il Sleep()a une précision en millisecondes , mais sa précision peut être supérieure de plusieurs ordres de grandeur. Vous pensez peut-être que vous dormez pendant 4 millisecondes, mais en fait, vous dormez pendant 400.
John Dibling

5
@John Dibling: Je pense qu'il utilise POSIX sleep, pas win32 Sleepétant donné "x secondes".
CB Bailey

1
Bien que C et C ++ aient un changement de nom différent, ce qui peut être une source de bogues et d'incompatibilités, dans la plupart des cas, il est bon d'utiliser des en-têtes C en C ++. Cependant, si vous voulez être absolument sûr que rien ne va mal, #includel'en-tête C à l'intérieur d'un extern "C" {}bloc. De plus, si vous avez des fichiers source C et C ++ dans le même projet, il est fortement recommandé de le faire afin d'éviter tout problème, surtout si vous incluez les mêmes en-têtes dans les deux types de fichiers source (auquel cas cela est nécessaire) . Si vous avez un projet purement C ++, il pourrait simplement fonctionner sans aucun problème.
adam10603

2
@JohnDibling non, pas 400 ms. La pire précision que vous ayez jamais obtenue GetTickCountprovenait de Windows 9x, qui avait une résolution de 55 ms; les versions ultérieures avaient une résolution de 16 ms ou moins. Un utilisateur a pensé qu'il obtenait une résolution de 16 ms à partir de Sleep, mais a ensuite déclaré que Sleeplui - même était assez précis, et l'imprécision apparente était causée par l'utilisation GetTickCountde la mesure du passage du temps.
Qwertie

Réponses:


457

Notez qu'il n'y a pas d'API C standard pour les millisecondes, donc (sous Unix) vous devrez vous contenter de usleep, qui accepte les microsecondes:

#include <unistd.h>

unsigned int microseconds;
...
usleep(microseconds);

2
Est-ce un sommeil occupé? J'ai besoin de céder à un autre fil pendant le sommeil; puis-je utiliser usleeppour ça?
Michael

13
Ce n'est pas une attente occupée stackoverflow.com/a/8156644/1206499 , et nanosleeppeut être un meilleur choix car usleepest obsolète.
jswetzen

4
Niet, pensez à mentionner la réponse de @ HighCommander4 qui est plus portable si vous avez un compilateur C ++ 11.
einpoklum

6
usleep () déconseillé dans POSIX en 2001 et supprimé en 2008.
Jetski S-type

1271

En C ++ 11, vous pouvez le faire avec les fonctionnalités de bibliothèque standard:

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

Clair et lisible, plus besoin de deviner quelles unités sleep()prend la fonction.


6
Std :: this_thread :: sleep_for définit-il un point d'interruption? Comme boost :: this_thread_sleep?
Martin Meeser

73
C'est la bonne façon de procéder. Période. Le fil est multiplateforme ainsi que chrono.
Néant

88
@Néant. Un très bon moyen certes, mais "la" et "la période" sont des mots terriblement forts.
Mad Physicist

5
Est-ce un sommeil occupé? J'ai besoin de céder à un autre fil pendant le sommeil; puis-je utiliser sleep_forpour ça?
Michael

14
@Michael: Ce n'est pas un sommeil occupé, il cédera à d'autres threads.
HighCommander4

83

Pour rester portable, vous pouvez utiliser Boost :: Thread pour dormir:

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

Cette réponse est en double et a déjà été publiée dans cette question . Vous pourriez peut-être y trouver également des réponses utilisables.


6
Gardez à l'esprit que - dans un environnement multi-thread - boost::this_thread::sleepajoute un point d'interruption à votre code. boost.org/doc/libs/1_49_0/doc/html/thread/…
Martin Meeser

35

Sous Unix, vous pouvez utiliser usleep .

Sous Windows, il y a Sleep .


4
et l'appel Windows est en millisecondes.
shindigo

17
Vous devez inclure <unistd.h> ou <Windows.h> respectivement.
gbmhunter

Oui, mais la résolution de temps réelle ne pourrait-elle pas être de 15-16 ms (même si l'unité dans l'appel est de 1 ms) et donc le temps minimum devrait être de 15-16 ms?
Peter Mortensen

33

Selon votre plate-forme, vous pouvez en avoir usleepou nanosleepdisponible usleepest obsolète et a été supprimé de la norme POSIX la plus récente; nanosleepest préféré.


6
Notez que while usleep()est déclaré dans <unistd.h>, confusément, nanosleep()est déclaré dans <time.h>/ <ctime>.
gbmhunter

27

Pourquoi ne pas utiliser la bibliothèque time.h? Fonctionne sur les systèmes Windows et 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;
}

Code corrigé - maintenant le CPU reste en état 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
L'un des problèmes avec ce code est qu'il s'agit d'une boucle occupée, il continuera à utiliser 100% d'un cœur de processeur unique. La fonction de veille est implémentée autour d'un appel du système d'exploitation qui mettra en veille le thread actuel et fera autre chose, et ne réveillera le thread que lorsque le temps spécifié expirera.
Ismael

Vous avez raison - il consommera 100% d'un cœur à un processeur. Voici donc du code réécrit en utilisant les fonctions de veille du système - et il est toujours multiplateforme:
Bart Grzybicki

@BartGrzybicki je sais que c'est une ancienne réponse et tout, mais dans Visual Studio 2017 sur une machine Windows, #ifdef WIN32ne s'évalue pas comme vrai par défaut.
kayleeFrye_onDeck

2
@kayleeFrye_onDeck Le code est incorrect. Ça devrait l'être #ifdef _WIN32.
Contango

1
@Contango Je le savais! Mais pas quand j'ai écrit ça ... lol. Merci pour le suivi!
kayleeFrye_onDeck

17

nanosleepest un meilleur choix que usleep- il est plus résistant aux interruptions.


6
J'étais familier usleep, mais pas nanosleep. Vous devez fournir un exemple de son utilisation sous Linux.
Jww


7

Si vous utilisez MS Visual C ++ 10.0, vous pouvez le faire avec les fonctionnalités de bibliothèque standard:

Concurrency::wait(milliseconds);

Tu auras besoin de:

#include <concrt.h>

10
N'utilisez pas le mot «standard» quand vous ne le pensez pas vraiment. <concrt.h>n'est pas un en-tête de bibliothèque standard - il peut s'agir d'une bibliothèque de plate-forme; dans ce cas, vous devez indiquer clairement les conditions préalables.
Toby Speight

5

Sur les plateformes avec la selectfonction (POSIX, Linux et Windows), vous pouvez faire:

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

Cependant, de meilleures alternatives sont disponibles de nos jours.


Impossible de compiler dans VS2017 sur une machine Windows:error LNK2019: unresolved external symbol _select@20 referenced in function "void __cdecl sleep(unsigned long)" (?sleep@@YAXK@Z)
kayleeFrye_onDeck

@kayleeFrye_onDeck Il compile. Ne lie tout simplement pas. Recherchez vos documents Windows.
Maxim Egorushkin

quel en-tête utilisez-vous pour timeval ??
Totte Karlsson

@TotteKarlsson <sys/time.h>.
Maxim Egorushkin

4

La façon de dormir votre programme en C ++ est la Sleep(int)méthode. Le fichier d'en-tête correspondant est#include "windows.h."

Par exemple:

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

Le temps de sommeil est mesuré en millisecondes et n'a pas de limite.

Second = 1000 milliseconds
Minute = 60000 milliseconds
Hour = 3600000 milliseconds

3
Que voulez-vous dire qu'il n'a pas de limite? Il a sûrement une limite qui est 0xFFFFFFFE. L'attente de 0xFFFFFFFF n'expirera tout simplement pas (ce qui signifie qu'il attendra la fin du programme).
Izzy

Je ne voulais pas dire ça comme ça Izzy, désolé pour notre malentendu. Je voulais dire que vous pouvez entrer n'importe quel nombre positif de millisecondes. Il faudra donc attendre plusieurs millisecondes pour fermer le programme. Si vous ne comprenez pas, dites-le, je vais vous expliquer plus.
Phi

Oui, mais quelle est la résolution temporelle réelle? Cela ne pourrait-il pas être de 15 à 16 ms dans certains cas? Par exemple, si vous utilisez Sleep (3), sera-t-il réellement en sommeil pendant 3 ms ou sera-t-il plutôt de 15-16 ms?
Peter Mortensen

3

Select call est un moyen d'avoir plus de précision (le temps de sommeil peut être spécifié en nanosecondes).


Bien que cela puisse être un indice précieux pour résoudre le problème, une bonne réponse démontre également la solution. Veuillez modifier pour fournir un exemple de code pour montrer ce que vous voulez dire. Vous pouvez également envisager d'écrire ceci en tant que commentaire.
Toby Speight

3

Utilisez les threads d'entrée / sortie asynchrones Boost, veillez pendant x millisecondes;

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

boost::thread::sleep(boost::get_system_time() + boost::posix_time::millisec(1000));

Que se passera-t-il réellement si vous essayez de dormir pendant 3 millisecondes? Sera-ce plutôt 15-16 millisecondes? L'avez-vous mesuré?
Peter Mortensen

1

La question est ancienne, mais j'ai réussi à trouver un moyen simple de l'avoir dans mon application. Vous pouvez créer une macro C / C ++ comme indiqué ci-dessous, utilisez-la:

#ifndef MACROS_H
#define MACROS_H

#include <unistd.h>

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

#endif // MACROS_H

1

De C ++ 14 en utilisant std et aussi ses littéraux numériques:

#include <chrono>
#include <thread>

using namespace std::chrono;

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

0

En remplacement de Win32 pour les systèmes POSIX:

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

while (1) {
    printf(".");
    Sleep((unsigned int)(1000.0f/20.0f)); // 20 fps
}

Préférez nanosleep()à usleep(): celle - ci est dépréciée et a été supprimé de la plus récente norme POSIX.
Toby Speight
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.