Escuche la pulsación de teclas en la aplicación de consola .NET
¿Cómo puedo continuar ejecutando mi aplicación de consola hasta que presione una tecla (como Escse presiona?)
Supongo que está envuelto en un bucle while. No me gusta ReadKey
porque bloquea la operación y solicita una tecla, en lugar de simplemente continuar y escuchar la pulsación de la tecla.
¿Cómo se puede hacer esto?
Úselo Console.KeyAvailable
para llamar solo ReadKey
cuando sepa que no se bloqueará:
Console.WriteLine("Press ESC to stop");
do {
while (! Console.KeyAvailable) {
// Do something
}
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
Puedes cambiar ligeramente tu enfoque: úsalo Console.ReadKey()
para detener tu aplicación, pero haz tu trabajo en un hilo en segundo plano:
static void Main(string[] args)
{
var myWorker = new MyWorker();
myWorker.DoStuff();
Console.WriteLine("Press any key to stop...");
Console.ReadKey();
}
En la myWorker.DoStuff()
función, luego invocaría otra función en un hilo en segundo plano (usando Action<>()
o Func<>()
es una manera fácil de hacerlo) y luego regresaría inmediatamente.
El camino más corto:
Console.WriteLine("Press ESC to stop");
while (!(Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape))
{
// do something
}
Console.ReadKey()
es una función de bloqueo, detiene la ejecución del programa y espera que se presione una tecla, pero gracias a verificar Console.KeyAvailable
primero, el while
bucle no se bloquea, sino que se ejecuta hasta que se Escpresiona.
Del vídeo curse Creación de aplicaciones de consola .NET en C# de Jason Roberts en http://www.pluralsight.com
Podríamos hacer lo siguiente para tener múltiples procesos en ejecución.
static void Main(string[] args)
{
Console.CancelKeyPress += (sender, e) =>
{
Console.WriteLine("Exiting...");
Environment.Exit(0);
};
Console.WriteLine("Press ESC to Exit");
var taskKeys = new Task(ReadKeys);
var taskProcessFiles = new Task(ProcessFiles);
taskKeys.Start();
taskProcessFiles.Start();
var tasks = new[] { taskKeys };
Task.WaitAll(tasks);
}
private static void ProcessFiles()
{
var files = Enumerable.Range(1, 100).Select(n => "File" + n + ".txt");
var taskBusy = new Task(BusyIndicator);
taskBusy.Start();
foreach (var file in files)
{
Thread.Sleep(1000);
Console.WriteLine("Procesing file {0}", file);
}
}
private static void BusyIndicator()
{
var busy = new ConsoleBusyIndicator();
busy.UpdateProgress();
}
private static void ReadKeys()
{
ConsoleKeyInfo key = new ConsoleKeyInfo();
while (!Console.KeyAvailable && key.Key != ConsoleKey.Escape)
{
key = Console.ReadKey(true);
switch (key.Key)
{
case ConsoleKey.UpArrow:
Console.WriteLine("UpArrow was pressed");
break;
case ConsoleKey.DownArrow:
Console.WriteLine("DownArrow was pressed");
break;
case ConsoleKey.RightArrow:
Console.WriteLine("RightArrow was pressed");
break;
case ConsoleKey.LeftArrow:
Console.WriteLine("LeftArrow was pressed");
break;
case ConsoleKey.Escape:
break;
default:
if (Console.CapsLock && Console.NumberLock)
{
Console.WriteLine(key.KeyChar);
}
break;
}
}
}
}
internal class ConsoleBusyIndicator
{
int _currentBusySymbol;
public char[] BusySymbols { get; set; }
public ConsoleBusyIndicator()
{
BusySymbols = new[] { '|', '/', '-', '\\' };
}
public void UpdateProgress()
{
while (true)
{
Thread.Sleep(100);
var originalX = Console.CursorLeft;
var originalY = Console.CursorTop;
Console.Write(BusySymbols[_currentBusySymbol]);
_currentBusySymbol++;
if (_currentBusySymbol == BusySymbols.Length)
{
_currentBusySymbol = 0;
}
Console.SetCursorPosition(originalX, originalY);
}
}
Aquí tienes una forma de hacer algo en un hilo diferente y comenzar a escuchar la tecla presionada en un hilo diferente. Y la Consola detendrá su procesamiento cuando finalice su proceso real o el usuario finalice el proceso presionando Escla tecla.
class SplitAnalyser
{
public static bool stopProcessor = false;
public static bool Terminate = false;
static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Split Analyser starts");
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Press Esc to quit.....");
Thread MainThread = new Thread(new ThreadStart(startProcess));
Thread ConsoleKeyListener = new Thread(new ThreadStart(ListerKeyBoardEvent));
MainThread.Name = "Processor";
ConsoleKeyListener.Name = "KeyListener";
MainThread.Start();
ConsoleKeyListener.Start();
while (true)
{
if (Terminate)
{
Console.WriteLine("Terminating Process...");
MainThread.Abort();
ConsoleKeyListener.Abort();
Thread.Sleep(2000);
Thread.CurrentThread.Abort();
return;
}
if (stopProcessor)
{
Console.WriteLine("Ending Process...");
MainThread.Abort();
ConsoleKeyListener.Abort();
Thread.Sleep(2000);
Thread.CurrentThread.Abort();
return;
}
}
}
public static void ListerKeyBoardEvent()
{
do
{
if (Console.ReadKey(true).Key == ConsoleKey.Escape)
{
Terminate = true;
}
} while (true);
}
public static void startProcess()
{
int i = 0;
while (true)
{
if (!stopProcessor && !Terminate)
{
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("Processing...." + i++);
Thread.Sleep(3000);
}
if(i==10)
stopProcessor = true;
}
}
}