如何在C#上的控制台应用程序中使用键盘输入停止正在运行的方法?
简言之,我正在利用C#进行科学计算,并且我已经编写了一个方法,该方法有一个while循环,可以运行到用户指定数量的步骤。。。实际上,这个方法可能需要很长时间才能执行(比如超过5个小时)。例如,当需要这么长时间时,我可能想停止按Esc键的方法 当我读到一些关于在时中断如何在C#上的控制台应用程序中使用键盘输入停止正在运行的方法?,c#,input,while-loop,user-input,break,C#,Input,While Loop,User Input,Break,简言之,我正在利用C#进行科学计算,并且我已经编写了一个方法,该方法有一个while循环,可以运行到用户指定数量的步骤。。。实际上,这个方法可能需要很长时间才能执行(比如超过5个小时)。例如,当需要这么长时间时,我可能想停止按Esc键的方法 当我读到一些关于在时中断的内容时,它就像一个布尔标志或类似的东西一样简单。所以我就这样想: public Double? Run(int n) { int i = 0; while ((i < n) && (/* inp
的内容时,它就像一个布尔
标志或类似的东西一样简单。所以我就这样想:
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
}
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() { }
}
public-Double?运行(int n)
{
int i=0;
而((i
这就是我一直想知道的。。。那么,你能在这方面给出一些有用的想法吗?我如何等待用户输入(我考虑了事件
,但我不确定如何在这里实现它,我认为如果在代码进入的每一步都必须听一个键,那么它会使代码更慢
嗯,有什么想法或意见吗
更新:我想我应该更好地描述这个问题。你给我的所有解决方案都可能解决我提出的这个问题,但我认为我对我真正的问题并不完全可靠。我不知道我是否应该问另一个问题或继续这个问题…如果你只是想停止应用程序,请按Ctrl-C从t开始命令行将执行此操作。如果您确实需要在长时间运行的进程中拦截输入,您可能希望生成一个工作线程来执行长时间运行的进程,然后只使用主线程与控制台交互(即console.ReadLine()).您可以从单独的线程运行此方法,并在按下键时设置停止变量:
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++;
}
}
您需要使用线程来完成此操作。启动任务时,生成一个新线程并在该线程上执行任务。然后在Program.cs中等待用户输入。如果用户输入了有意义的内容(在您的情况下,Esc
键),则会提醒后台线程该操作。最简单的方法是设置静态后台线程将检查此静态变量,当它被更改时,后台线程将清理自身并中止
看
代码示例将更深入一些,但它看起来是这样的:
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
}
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() { }
}
Console.key上的池可及时使用,并采取相应的措施。使用系统;
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");
}
}
使用System.Threading.Tasks;
命名空间控制台应用程序4
{
班级计划
{
静态布尔值_取消=假;
静态void Main(字符串[]参数)
{
var computationTask=Task.Factory.StartNew(性能可信计算);
var acceptCancelKey=Task.Factory.StartNew(AcceptCancel);
而(!acceptCancelKey.IsCompleted&!computationTask.IsCompleted)
{
计算任务。等待(100);
}
if(acceptCancelKey.IsCompleted&!computationTask.IsCompleted)
{
computationTask.Wait(new System.Threading.CancellationToken());
}
如果(!acceptCancelKey.IsCompleted)完成,则为else
{
acceptCancelKey.Wait(新系统.Threading.CancellationToken());
}
}
私有静态无效性能可信计算()
{
Console.WriteLine(“执行计算”);
int ticks=Environment.TickCount;
int diff=Environment.TickCount-滴答声;
同时(!\u取消&&diff<10000)
{
//计算
}
Console.WriteLine(“计算完成”);
}
私有静态void AcceptCancel()
{
var key=Console.ReadKey(true);
控制台写入线(“按Esc键取消”);
while(key.key!=ConsoleKey.Escape)
{
key=Console.ReadKey(true);
}
_取消=真;
控制台。写入(“计算被取消”);
}
}
}我同意,看看BackgroundWorker:同意。后台工作人员是最好的方法。您甚至可以生成多个线程,以便“长时间运行的进程”可以少一点长时间运行。我已经为我构建的GUI应用程序使用了BackgroundWorker,但我不知道我也可以在控制台应用程序中使用它。现在,关于你的第一点,我不能只使用CTRL C,因为这只是一个简单的例子……实际上我运行了run()
方法几十次,并对返回的值进行平均,我对各种参数集执行此操作,打算在程序结束时编写一个文件…我的观点是,如果我按CTRL C,程序肯定会停止,而不仅仅是跳过一个值…你看到了吗?感谢bg工作人员的提示!我认为你的想法或多或少是正确的杰夫的主意不是吗?谢谢两个!我认为你的主意或多或少是马克的主意,不是吗?谢谢两个!@杰夫:不过要小心;如果不锁定,这不是线程安全的(你会遇到竞争条件).@Girardi是的,我们的建议几乎是一样的。@Mark你是对的。我只是想给Girardi提供一个样本,我不打算模拟整个9码。而且,观众有限的情况听起来很简单,所以比赛条件可能是一个边缘情况。不过,锁定绝对是正确的选择。@Jeff:我只是想指出一点;实际上,我之前有一篇帖子被删除了,因为我对一个例子没有完全的线程安全性,所以我学会了明确:-)