按键我如何可以继续运行我的控制台应用程序,直到一个按键(如Esc键按下?)聆听到.NET控制台应用程序
我假设它围绕一个while循环包裹。我不喜欢ReadKey
,因为它会阻止操作并要求输入密钥,而不是继续听按键。
这怎么办?
按键我如何可以继续运行我的控制台应用程序,直到一个按键(如Esc键按下?)聆听到.NET控制台应用程序
我假设它围绕一个while循环包裹。我不喜欢ReadKey
,因为它会阻止操作并要求输入密钥,而不是继续听按键。
这怎么办?
使用Console.KeyAvailable
,所以你只叫ReadKey
当你知道它不会阻止:
Console.WriteLine("Press ESC to stop");
do {
while (! Console.KeyAvailable) {
// Do something
}
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
可以稍微改变你的方法 - 使用Console.ReadKey()
停止你的应用程序,但做你的工作在后台线程:
static void Main(string[] args)
{
var myWorker = new MyWorker();
myWorker.DoStuff();
Console.WriteLine("Press any key to stop...");
Console.ReadKey();
}
在myWorker.DoStuff()
功能,那么你会调用后台线程的另一个功能(使用Action<>()
或Func<>()
是一个简单的方法来做到这一点),然后立即返回。
这里是一个办法为你做在不同的线程东西,并开始听在按下的键不同的线程。当您的实际过程结束或用户通过按Esc键结束过程时,控制台将停止处理。
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;
}
}
}
的捷径:
Console.WriteLine("Press ESC to stop");
while (!(Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape))
{
// do something
}
Console.ReadKey()
是一个阻塞函数,它停止程序和按键等待的执行,但由于检查Console.KeyAvailable
第一,while
循环不是阻止,但运行,直到按下Esc。
这里可能是最好的答案...非常有帮助谢谢! – 2016-12-30 18:50:14
如果您使用Visual Studio,则可以使用“调试”菜单中的“无需调试即可开始”。
它会自动写入“按任意键继续...”在完成应用程序后,您可以将控制台留给您,直到按下某个按键。
从C#中的视频诅咒大厦.NET控制台应用程序由贾森·罗伯茨在http://www.pluralsight.com
我们可以做到以下有多个正在运行的进程
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);
}
}
根据我的经验,在控制台应用程序最简单的(按箭头键示例):
ConsoleKey readKey = Console.ReadKey().Key;
if (readKey == ConsoleKey.LeftArrow) {
<Method1>(); //Do something
} else if (readKey == ConsoleKey.RightArrow) {
<Method2>(); //Do something
}
我用来避免循环,而不是我w在方法中使用上面的代码,我在“Method1”和“Method2”的末尾调用它,因此,在执行“Method1”或“Method2”之后,Console.ReadKey().Key已准备好读取密钥再次。
解决的情况下,一些其他的答案不处理好:
许多此页面上的解决方案,涉及轮询Console.KeyAvailable
或阻塞Console.ReadKey
。尽管.NET Console
在这里不是很合作,但您可以使用Task.Run
转向更现代的Async
收听模式。
主要的问题需要注意的是,默认情况下,您的控制台线程没有设置为Async
操作 - 这意味着,当你摔倒了你main
功能的底部,而不是等待Async
落成,你的AppDoman和过程将结束。解决这个问题的正确方法是使用Stephen Cleary的AsyncContext在您的单线程控制台程序中建立完整的Async
支持。但对于更简单的情况,如等待按键,安装完整的trampoline可能会过度。
下面的例子是用于某种迭代批处理文件中的控制台程序。在这种情况下,当程序完成其工作时,通常它应该退出而不需要需要按键,然后我们允许一个可选的按键到阻止该应用程序退出。我们可以暂停周期来检查事情,可能会恢复,或者使用暂停作为已知的“控制点”,以彻底打破批处理文件。
static void Main(String[] args)
{
Console.WriteLine("Press any key to prevent exit...");
var tHold = Task.Run(() => Console.ReadKey(true));
// ... do your console app activity ...
if (tHold.IsCompleted)
{
#if false // For the 'hold' state, you can simply halt forever...
Console.WriteLine("Holding.");
Thread.Sleep(Timeout.Infinite);
#else // ...or allow continuing to exit
while (Console.KeyAvailable)
Console.ReadKey(true); // flush/consume any extras
Console.WriteLine("Holding. Press 'Esc' to exit.");
while (Console.ReadKey(true).Key != ConsoleKey.Escape)
;
#endif
}
}
但是,如果你这样做而不是readLine(),你失去了通过按“向上”键进行历史回忆的真棒功能。 – 2015-07-01 08:17:09
@ v.oddou在最后一行之后,只需添加你的'Console.ReadLine()',你就被设置了,不是吗? – Gaffi 2016-01-16 01:13:07