Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stop a running method with keyboard input in a Console Application on C#?

In short, I'm utilizing C# to scientific computation and I've written a method that has a while loop that may run to a user-specified quantity of steps... Actually, this method may take too long to execute (like more than 5 hours). When it takes this long, I may want to stop the method pressing Esc key, for example.

As I read something about breaking while, it is as simple as a Boolean flag or something like this. So I thought in something like this:

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
}

Well, this is what I wondered until now... So please, could you give useful ideas to this extent? How can I wait for a user input (I thought about Events, but I'm not sure how to implement it here and I think that it will make the code even slower, if I have to listen to a key at every while step the code goes into...

Well, any ideas or comments?


Update: I think I should have had described better the problem. All the solutions you gave me may solve this problem I proposed, but I think I was not completely reliable to my real problem. I don't know if I should ask another question or keep with this one...

like image 870
Girardi Avatar asked Feb 21 '11 16:02

Girardi


3 Answers

You could run this method from a separate thread and set a stop variable when a key is pressed:

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++;
    }
}

and when a key is pressed, update stopProcessing accordingly:

Console.ReadKey();
lock(myLock)
{
    stopProcessing = true;
}
like image 135
Mark Avenius Avatar answered Sep 21 '22 02:09

Mark Avenius


If you're just wanting to stop the application, Ctrl-C from the command line will do it. If you really need to intercept input during a long running process, you might want to spawn a worker thread to do the long running process and then just use the main thread to interact with the console (i.e. Console.ReadLine()).

like image 42
Brady Holt Avatar answered Sep 19 '22 02:09

Brady Holt


You will need to do this using threading. When you start the task, spawn a new thread and execute the task on that thread. Then in your Program.cs, wait for user input. If the user enters something meaningful - in your case, the Esc key - alert the background thread of the action. The simplest way to do this is by setting a static variable. The background thread will be checking this static variable and when it has been changed, the background thread will clean itself up and abort.

See the MSDN article on Threading.

A code sample will be a little more in depth, but it would look something like this:

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() { }

}
like image 24
Jeff Avatar answered Sep 18 '22 02:09

Jeff