如何在 C# 的控制台应用程序中使用键盘输入停止正在运行的方法?
Posted
技术标签:
【中文标题】如何在 C# 的控制台应用程序中使用键盘输入停止正在运行的方法?【英文标题】:How to stop a running method with keyboard input in a Console Application on C#? 【发布时间】:2011-07-01 09:33:04 【问题描述】:简而言之,我正在使用 C# 进行科学计算,并且我编写了一个方法,它有一个 while 循环,可以运行到用户指定数量的步骤...实际上,这个方法可能需要很长时间才能执行(比如超过 5 个小时)。例如,当需要这么长时间时,我可能想停止按 Esc 键的方法。
当我读到一些关于破坏while
的内容时,它就像Boolean
标志或类似的东西一样简单。所以我想到了这样的事情:
public Double? Run(int n)
int i = 0;
while ((i < n) && (/* inputkey != ConsoleKey.Escape */))
// here goes the heavy computation thing
// and I need to read some "inputkey" as well to break this loop
i++;
// I'm not worried about the return statement, as it is easy to do...
// returns null if the user skipped the method by pressing Escape
// returns null if the method didn't converged
// returns the double value that the method calculated otherwise
嗯,这就是我到现在为止一直想知道的......那么,请你提供一些有用的想法吗?我如何等待用户输入(我考虑过Events
,但我不确定如何在这里实现它,我认为如果我必须每隔一段时间听一个键,它会使代码变得更慢代码进入的步骤...
嗯,有什么想法或方法吗?
更新:我想我应该更好地描述这个问题。您给我的所有解决方案都可能解决我提出的这个问题,但我认为我对我的实际问题并不完全可靠。我不知道我是应该问另一个问题还是继续这个问题......
【问题讨论】:
【参考方案1】:如果您只是想停止应用程序,可以使用命令行中的 Ctrl-C 来完成。如果您确实需要在长时间运行的过程中截取输入,您可能希望生成一个工作线程来执行长时间运行的过程,然后只需使用主线程与控制台交互(即 Console.ReadLine())。
【讨论】:
我同意,看看BackgroundWorker:msdn.microsoft.com/en-us/library/… 同意。 Background Worker 是最好的方法。您甚至可以生成多个线程,这样您的“长时间运行的进程”就可以少一些运行时间。 好吧,我已经将 BackgroundWorker 用于我构建的 GUI 应用程序,但我不知道我也可以在控制台应用程序中使用它。现在,关于您的第一点,我不能只使用 CTRL C,因为这只是我所拥有的一个简单示例......实际上我运行了Run()
方法数十次并使用返回值执行平均值,我对各种参数集执行此操作,打算在程序末尾写入一个文件...我的意思是,如果我按 CTRL C,程序肯定会停止,不仅会跳过一个值...你明白吗?感谢bg工作者的提示!【参考方案2】:
您可以从一个单独的线程运行此方法,并在按下某个键时设置一个停止变量:
object myLock = new object();
bool stopProcessing = false;
public Double? Run(int n)
int i = 0;
while (i < n)
lock(myLock)
if(stopProcessing)
break;
// here goes the heavy computation thing
// and I need to read some "inputkey" as well to break this loop
i++;
当一个键被按下时,相应地更新 stopProcessing:
Console.ReadKey();
lock(myLock)
stopProcessing = true;
【讨论】:
我认为你的想法或多或少是杰夫的想法,不是吗?谢谢你们!【参考方案3】:您需要使用线程来执行此操作。启动任务时,生成一个新线程并在该线程上执行任务。然后在您的 Program.cs 中,等待用户输入。如果用户输入了一些有意义的东西 - 在你的情况下,Esc
键 - 提醒后台线程该操作。最简单的方法是设置一个静态变量。后台线程将检查这个静态变量,当它被更改时,后台线程将自行清理并中止。
请参阅MSDN article on Threading。
代码示例会更深入一点,但它看起来像这样:
public class Program.cs
public static myFlag = false;
public void Main()
thread = new Thread(new ThreadStart(DoWork));
thread.Start();
Console.ReadLine();
myFlag = true;
public static DoWork()
while(myFlag == false)
DoMoreWork();
CleanUp()
public static DoMoreWork()
public static CleanUp()
【讨论】:
我认为你的想法或多或少是马克的想法,不是吗?谢谢你们! @Jeff:不过要小心;如果没有锁定,这不是线程安全的(你会遇到竞争条件)。 @Girardi 是的,我们提出了几乎相同的建议。 @Mark 你是对的。我只是想为 Girardi 提供一个样品,我并没有打算模拟整个 9 码。此外,在观众有限的情况下,情况听起来很简单,所以比赛条件可能是一个极端情况。尽管如此,锁定绝对是正确的方法。 @Jeff:我只是想指出一点;实际上,我之前已经删除了我的一个帖子,因为我没有完全线程安全的例子,所以我学会了明确:-)【参考方案4】:及时在Console.KeyAvailable上池并采取相应措施。
【讨论】:
【参考方案5】:using System;
using System.Threading.Tasks;
namespace ConsoleApplication4
class Program
static bool _cancelled = false;
static void Main( string[] args )
var computationTask = Task.Factory.StartNew(PerformIncredibleComputation);
var acceptCancelKey = Task.Factory.StartNew(AcceptCancel);
while (!acceptCancelKey.IsCompleted && ! computationTask.IsCompleted)
computationTask.Wait (100);
if( acceptCancelKey.IsCompleted && !computationTask.IsCompleted )
computationTask.Wait (new System.Threading.CancellationToken ());
else if(!acceptCancelKey.IsCompleted)
acceptCancelKey.Wait(new System.Threading.CancellationToken());
private static void PerformIncredibleComputation()
Console.WriteLine("Performing computation.");
int ticks = Environment.TickCount;
int diff = Environment.TickCount - ticks;
while (!_cancelled && diff < 10000)
//computing
Console.WriteLine("Computation finished");
private static void AcceptCancel()
var key = Console.ReadKey(true);
Console.WriteLine("Press Esc to cancel");
while(key.Key != ConsoleKey.Escape)
key = Console.ReadKey(true);
_cancelled = true;
Console.Write("Computation was cancelled");
【讨论】:
以上是关于如何在 C# 的控制台应用程序中使用键盘输入停止正在运行的方法?的主要内容,如果未能解决你的问题,请参考以下文章