Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C#上的控制台应用程序中使用键盘输入停止正在运行的方法?_C#_Input_While Loop_User Input_Break - Fatal编程技术网

如何在C#上的控制台应用程序中使用键盘输入停止正在运行的方法?

如何在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

简言之,我正在利用C#进行科学计算,并且我已经编写了一个方法,该方法有一个while循环,可以运行到用户指定数量的步骤。。。实际上,这个方法可能需要很长时间才能执行(比如超过5个小时)。例如,当需要这么长时间时,我可能想停止按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() { }

}
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:我只是想指出一点;实际上,我之前有一篇帖子被删除了,因为我对一个例子没有完全的线程安全性,所以我学会了明确:-)