128 votes

Comment maintenir une application console .NET en fonctionnement ?

Considérons une application Console qui démarre certains services dans un thread séparé. Il ne lui reste plus qu'à attendre que l'utilisateur appuie sur Ctrl+C pour l'arrêter.

Laquelle des propositions suivantes est la meilleure façon de procéder ?

static ManualResetEvent _quitEvent = new ManualResetEvent(false);

static void Main() {
    Console.CancelKeyPress += (sender, eArgs) => {
        _quitEvent.Set();
        eArgs.Cancel = true;
    };

    // kick off asynchronous stuff 

    _quitEvent.WaitOne();

    // cleanup/shutdown and quit
}

Ou ceci, en utilisant Thread.Sleep(1) :

static bool _quitFlag = false;

static void Main() {
    Console.CancelKeyPress += delegate {
        _quitFlag = true;
    };

    // kick off asynchronous stuff 

    while (!_quitFlag) {
        Thread.Sleep(1);
    }

    // cleanup/shutdown and quit
}

78voto

Mike Points 458

Vous voulez toujours éviter d'utiliser les boucles while, surtout lorsque vous obligez le code à revérifier les variables. Cela gaspille les ressources du processeur et ralentit votre programme.

Je dirais certainement le premier.

3 votes

+1. En outre, puisque le bool n'est pas déclaré comme volatile il y a une possibilité certaine que les lectures ultérieures de _quitFlag dans le while serait optimisée, ce qui conduirait à une boucle infinie.

2 votes

Il manque la façon recommandée de le faire. J'attendais cette réponse.

34voto

Cocowalla Points 4798

Une solution plus simple est également possible :

Console.ReadLine();

0 votes

J'allais le suggérer, mais ça ne s'arrête pas seulement à Ctrl-C.

0 votes

J'ai eu l'impression que CTRL-C était juste un exemple - n'importe quelle entrée de l'utilisateur pour le fermer.

2 votes

Rappelez-vous que 'Console.ReadLine()' bloque les threads. L'application continue donc de fonctionner mais ne fait rien d'autre que d'attendre que l'utilisateur entre une ligne.

13voto

Thomas Levesque Points 141081

Vous pouvez le faire (et supprimer le CancelKeyPress gestionnaire d'événement) :

while(!_quitFlag)
{
    var keyInfo = Console.ReadKey();
    _quitFlag = keyInfo.Key == ConsoleKey.C
             && keyInfo.Modifiers == ConsoleModifiers.Control;
}

Je ne sais pas si c'est mieux, mais je n'aime pas l'idée d'appeler Thread.Sleep dans une boucle.. Je pense que c'est plus propre de bloquer sur l'entrée de l'utilisateur.

0 votes

Je n'aime pas que vous vérifiez les touches Ctrl+C, au lieu du signal déclenché par Ctrl+C.

8voto

CRice Points 4717

Il est également possible de bloquer le thread/programme sur la base d'un jeton d'annulation.

token.WaitHandle.WaitOne();

WaitHandle est signalé lorsque le jeton est annulé.

J'ai vu cette technique utilisée par le Microsoft.Azure.WebJobs.JobHost, où le jeton provient d'une source de jeton d'annulation du WebJobsShutdownWatcher (un observateur de fichiers qui termine le travail).

Cela donne un certain contrôle sur le moment où le programme peut se terminer.

1 votes

C'est une excellente réponse pour toute application de console du monde réel qui doit écouter une CTL+C parce qu'il effectue une opération de longue durée, ou qu'il s'agit d'un démon, qui devrait également arrêter de manière élégante ses threads de travail. Vous feriez cela avec un CancelToken, et cette réponse tire donc parti d'une fonction WaitHandle qui existerait déjà, plutôt que d'en créer une nouvelle.

7voto

ygaradon Points 428

Je préfère utiliser le Application.Run

static void Main(string[] args) {

   //Do your stuff here

   System.Windows.Forms.Application.Run();

   //Cleanup/Before Quit
}

de la documentation :

Commence à exécuter une boucle de messages d'application standard sur le thread actuel, sans formulaire.

14 votes

Mais alors vous prenez une dépendance sur les formulaires Windows juste pour cela. Ce n'est pas un problème majeur avec le framework .NET traditionnel, mais la tendance actuelle est aux déploiements modulaires qui ne comprennent que les parties dont vous avez besoin.

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