Comment interrompre la Console.ReadLine
Est-il possible d'arrêter le Console.ReadLine()
par programmation?
J'ai une application console: la grande partie de la logique s'exécute sur un autre thread et dans le thread principal j'accepte entrée à l'aide de Console.ReadLine()
. J'aimerais arrêter de lire à partir de la console lorsque le thread séparé arrêter de courir.
Comment puis-je y parvenir?
- voir stackoverflow.com/questions/8984838/...
- Ok, cette question est vieux mais il y a eu quelques changements depuis elle a été posée et la réponse est ici. Si vous frappez à cette question, comme je l'ai fait, découvrez ma réponse ci-dessous qui peuvent vous aider.
Vous devez vous connecter pour publier un commentaire.
Mise à JOUR: cette technique n'est plus fiable sur Windows 10. Ne l'utilisez pas s'il vous plaît.
Assez lourd de la mise en œuvre des changements dans Win10 de faire une console se comporte plus comme un terminal. Sans doute pour aider à la nouvelle Linux sous-système. Un (involontaire?) l'effet secondaire est que CloseHandle() blocages jusqu'à ce qu'une lecture est terminée, le meurtre de ce approche de la mort. Je vais laisser le post original en place, seulement parce qu'il pourrait aider quelqu'un à trouver une alternative.
C'est possible, vous devez vous branler le tapis de sol en fermant le flux stdin. Ce programme témoigne de l'idée:
AllocConsole
avec une course deConsole.ReadLine
, il en résulte uneIOException
: "Le handle n'est pas valide."Envoyer [enter] pour le cours d'exécution application console:
Ce code envoie [enter] dans l'actuel processus de console, l'abandon de toute ReadLine() appelle le blocage dans le code non managé profondément dans le noyau de windows, ce qui permet à la C# thread pour sortir naturellement.
J'ai utilisé ce code à la place de la réponse qui implique la fermeture de la console, en raison de la fermeture de la console signifie que ReadLine() et ReadKey() sont désactivé de façon permanente à partir de ce point dans le code (il lève une exception si utilisé).
Cette réponse est supérieure à toutes les solutions qui impliquent SendKeys et D'Entrée De Windows Simulateur, comme il fonctionne même si l'application n'a pas le focus.
J'ai besoin d'une solution qui serait de travailler avec Mono, donc pas d'appels d'API. Je poste ce encadrez quelqu'un d'autre est dans la même situation, ou s'il veut une pure C# moyen de le faire. Le CreateKeyInfoFromInt() la fonction est la partie la plus délicate (certaines touches sont plus d'un octet de longueur). Dans le code ci-dessous, ReadKey() lève une exception si ReadKeyReset() est appelée à partir d'un autre thread. Le code ci-dessous n'est pas entièrement terminée, mais il n'démontrer le concept de l'utilisation de la Console existante C# fonctions pour créer un interuptable GetKey() fonction.
Console.KeyAvailable
avecConsole.ReadKey
directement? Une autre question: N'est-ce pas de 50 ms à filer plus de ressources que de laisserReadKey
d'attendre le prochain événement d'entrée?L'actuel accepté de répondre ne fonctionne plus alors j'ai décidé d'en créer un nouveau. La seule façon de le faire est de créer votre propre
ReadLine
méthode, je pense, de nombreux de nombreux scénarios nécessitant une telle fonctionnalité et le code ici met en œuvre l'un d'entre eux:Placer cette fonction quelque part dans votre code et cela vous donne une fonction qui peut être annulé par l'intermédiaire d'un
CancellationToken
aussi pour mieux le code que j'ai utiliséCette fonction retourne une chaîne vide en cas d'annulation (ce qui était bon pour mon cas), vous pouvez jeter une exception à l'intérieur de l'marqué
catch
expression ci-dessus si vous le souhaitez.Également dans le même
catch
expression, vous pouvez supprimer lestringBuilder.Clear();
ligne et qui va provoquer le code de retour de ce que l'utilisateur a entré jusqu'à présent. Combinez cela avec un succès ou de l'annulation de drapeau et vous pouvez garder ce que l'entrée et de l'utiliser dans de nouvelles demandes.Autre chose que vous pouvez changer, c'est que vous pouvez définir un délai d'attente en plus de l'annulation de jeton dans la boucle si vous souhaitez obtenir un délai d'attente de la fonctionnalité.
J'ai essayé d'être aussi propre que j'ai besoin mais ce code peut être plus propre. La méthode peut devenir
async
lui-même et sur le délai et le jeton d'annulation passée dans.J'étais également à la recherche d'un moyen pour arrêter la lecture à partir de la console dans certaines conditions. la solution je suis venu avec était de faire un non bloquant la version de ligne de lecture avec ces deux méthodes.
cela nous permet d'avoir ReadLine sur le thread séparé et nous pouvons l'attendre ou l'utiliser dans d'autres lieux sous certaines conditions.
Ceci est une version modifiée de Contango de réponse. Au lieu d'utiliser le processus actuel de MainWindowhandle, ce code utilise GetForegroundWindow() pour obtenir la Console MainWindowHandle si lancé à partir de cmd.
Facultatif
Vérifier pour voir si la fenêtre de premier plan a été cmd. Si ce n'était pas le cas, le processus actuel devrait lancer la fenêtre de la console pour aller de l'avant et de l'utiliser. Cela ne devrait pas d'importance parce que la fenêtre de premier plan devrait être le processus en cours de la fenêtre de toute façon, mais cela aide à vous sentir bien à ce sujet par une double vérification.
Ce sera procédé à un Ctrl+C dans un sujet séparé pendant que votre application est en attente d'une Console.Readline():