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 ++?

Prasanth Madhavan
la source
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);
Niet l'Absolu Noir
la source
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.

HighCommander4
la source
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.

MOnsDaR
la source
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 .

INS
la source
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é.

CB Bailey
la source
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;
}
Bart Grzybicki
la source
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.

Johan Kotlinski
la source
6
J'étais familier usleep, mais pas nanosleep. Vous devez fournir un exemple de son utilisation sous Linux.
Jww
14
#include <windows.h>

Syntaxe:

Sleep (  __in DWORD dwMilliseconds   );

Usage:

Sleep (1000); //Sleeps for 1000 ms or 1 sec
foobar
la source
3
Que devez-vous inclure pour cela?
ʇolɐǝz ǝɥʇ qoq
#include <WinBase.h>
foobar
7
Non, vous devez#include <windows.h>
ʇolɐǝz ǝɥʇ qoq
7
La question implique fortement qu'une solution POSIX est requise.
Toby Speight
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>
Metronit
la source
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.

Maxim Egorushkin
la source
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
Phi
la source
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).

Madhava Gaikwad
la source
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));
Anum Sheraz
la source
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
VPZ
la source
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);
Martin Flaska
la source
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
}
lama12345
la source
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