53 votes

Boucle infinie conviviale pour le processeur

L'écriture d'une boucle infinie est simple:

while(true){
    //add whatever break condition here
}

Mais ce sera poubelle la performance du CPU. Ce thread d'exécution prendra autant que possible de la CPU de puissance.

Quel est le meilleur moyen pour diminuer l'impact sur le CPU? L'ajout de quelques Thread.Sleep(n) devrait faire l'affaire, mais la définition d'une haute valeur de délai d'expiration pour l' Sleep() méthode peut indiquer une application qui ne répond pas au système d'exploitation.

Disons que j'ai besoin pour effectuer une tâche chaque minute ou deux dans une application console. J'ai besoin de garder Main() cours d'exécution dans une "boucle infinie", tandis qu'un timer déclenche l'événement qui va faire le travail. J'aimerais conserver Main() avec l'impact le plus faible sur le CPU.

Quelles sont les méthodes que vous proposez. Sleep() peut être ok, mais comme je l'ai déjà mentionné, cela pourrait indiquer un insensible fil pour le système d'exploitation.

PLUS TARD EDIT:

Je veux expliquer mieux ce que je suis à la recherche de:

  1. J'ai besoin d'une application console pas de service Windows. Console les applications peuvent simuler les services Windows sur Windows Mobile 6.x systèmes avec le Compact Framework.

  2. J'ai besoin d'un moyen de garder l'application en vie aussi longtemps que l'appareil Windows Mobile est en cours d'exécution.

  3. Nous savons tous que l'application de console s'exécute tant que ses statique de la fonction main() s'exécute, j'ai donc besoin d'un moyen de prévenir la fonction main() de sortie.

  4. Dans des situations particulières (comme: mise à jour de l'application), j'ai besoin de demander l'application d'arrêter, j'ai donc besoin de boucle à l'infini et de test pour certains sortie de la condition. Par exemple, c'est pourquoi, Console.ReadLine() n'est d'aucune utilité pour moi. Il n'y a pas de sortie contrôle de condition.

  5. À ce sujet, je tiens à ce que la fonction main() en tant que ressource conviviale que possible. Laissez asside l'empreinte de la fonction qui vérifie la condition de sortie.

51voto

Oliver Points 19006

Pour éviter la boucle infinie, utilisez simplement un WaitHandle . Pour quitter le processus du monde extérieur, utilisez un EventWaitHandle avec une chaîne unique. Voici un exemple.

Si vous le démarrez pour la première fois, un message est imprimé toutes les 10 secondes. Si vous démarrez entre-temps une seconde instance du programme, il informera l'autre processus de quitter et de se quitter de manière élégante également immédiatement. Utilisation du processeur pour cette approche: 0%

 private static void Main(string[] args)
{
    // Create a IPC wait handle with a unique identifier.
    bool createdNew;
    var waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, "CF2D4313-33DE-489D-9721-6AFF69841DEA", out createdNew);
    var signaled = false;

    // If the handle was already there, inform the other process to exit itself.
    // Afterwards we'll also die.
    if (!createdNew)
    {
        Log("Inform other process to stop.");
        waitHandle.Set();
        Log("Informer exited.");

        return;
    }

    // Start a another thread that does something every 10 seconds.
    var timer = new Timer(OnTimerElapsed, null, TimeSpan.Zero, TimeSpan.FromSeconds(10));

    // Wait if someone tells us to die or do every five seconds something else.
    do
    {
        signaled = waitHandle.WaitOne(TimeSpan.FromSeconds(5));
        // ToDo: Something else if desired.
    } while (!signaled);

    // The above loop with an interceptor could also be replaced by an endless waiter
    //waitHandle.WaitOne();

    Log("Got signal to kill myself.");
}

private static void Log(string message)
{
    Console.WriteLine(DateTime.Now + ": " + message);
}

private static void OnTimerElapsed(object state)
{
    Log("Timer elapsed.");
}
 

9voto

sll Points 30638

Vous pouvez utiliser le Système.Le filetage.La minuterie de la Classe qui fournit de la capacité d'exécution de rappel asynchrone dans une période de temps donnée.

public Timer(
    TimerCallback callback,
    Object state,
    int dueTime,
    int period
)

Comme alternative il y a le Système.Les minuteries.Minuterie de classe qui expose Écoulé Événement qui soulève lors d'une période de temps est écoulé.

1voto

anothershrubery Points 6104

Pourquoi voudriez-vous tolérer l'utilisation d'une boucle infinie? Pour cet exemple, configurer le programme comme une tâche planifiée, à exécuter toutes les minutes, ne serait pas plus économique?

1voto

Christophe Geers Points 4595

Pourquoi ne pas vous écrire une petite application et de l'utilisation du système planificateur de tâches à exécuter à chaque minute, heure, etc...?

Une autre option serait d'écrire un Service Windows qui s'exécute en arrière-plan. Le service pourrait utiliser une Alarme simple classe comme suit sur MSDN:

http://msdn.microsoft.com/en-us/library/wkzf914z%28v=VS.90%29.aspx#Y2400

Vous pouvez l'utiliser pour déclencher périodiquement votre méthode. En interne, cette Alarme classe utilise un timer:

http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx

Il suffit de régler la minuterie d'intervalle correctement (par exemple, 60000 millisecondes) et il va déclencher l'événement Écoulée périodiquement. Associer un gestionnaire d'événement pour l'événement Écoulé pour accomplir votre tâche. Pas besoin de mettre en œuvre une "boucle infinie" juste pour garder l'application en vie. Ce sont gérées par le service.

-1voto

Peter Points 2762

Pour que les applications de la console continuent de fonctionner, il suffit d’ajouter un Console.ReadLine() à la fin de votre code dans Main() .

Si l'utilisateur ne peut pas mettre fin à l'application, vous pouvez le faire avec une boucle comme celle-ci:

 while (true){
   Console.ReadLine();
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X