0

Consider a Console application that starts up some services in a separate thread. All it needs to do is wait for the user to press Ctrl+C to shut it down.

I already tried some examples, but all examples work with "do while".

Consider this code :

static void Main(string[] args)
{
    for (long ContactId = 0; ContactId < 1000; ContactId++)
    {
        try
        {
            Task.WaitAll(CreateJson(ContactId));
        }
        catch (Exception ex)
        {
            System.IO.File.AppendAllText("error.txt", ContactId + "\n", encoding);
        }
    }

    Console.WriteLine("Finalizado em " + watch.Elapsed + "");
    Console.ReadKey();
 }

How can I do some "listener" to stop the all the process and exit the console?

I already tried this example but not works fine for me (How to keep a .NET console app running?)

Thanks

Community
  • 1
  • 1
Jhonathan
  • 330
  • 1
  • 2
  • 14
  • `CreateJson` opens up a new *process* for each invocation? – Yuval Itzchakov Dec 04 '15 at 14:44
  • So you are looking for a way to cancel `CreateJson`? – Yacoub Massad Dec 04 '15 at 14:44
  • Yes, cancel the task CreateJson and exit the console after "Esc" or Ctrl + C, for example. – Jhonathan Dec 04 '15 at 14:46
  • Please add your `CreateJson` method to the question. – Yuval Itzchakov Dec 04 '15 at 14:47
  • You would have to program `CreateJson` to take in a `CancellationToken` and to respond to a cancellation request. This is not straightforward and depends on how `CreateJson` is implemented. – Yacoub Massad Dec 04 '15 at 14:48
  • Getting the program to stop is certainly not a problem. Getting it to do something when the user terminates it requires using pinvoke. You'll find lots of examples when you google "c# setconsolectrlhandler". – Hans Passant Dec 04 '15 at 14:51
  • @HansPassant: for control+c/break, isn't [static event Console.CancelKeyPress](https://msdn.microsoft.com/en-us/library/system.console.cancelkeypress(v=vs.110).aspx) enough? If I remember well, it was not called when user closes the console window, but for me it caught Ctrl+C just fine. – quetzalcoatl Dec 04 '15 at 15:03
  • Yes, but it did not make sense at all (to me anyway) that he would write a manual to tell the user to use Ctrl+C instead of just clicking the Close button. – Hans Passant Dec 04 '15 at 15:19

1 Answers1

3

There's an event on Console class that will help you detect that user pressed control+c

Console.CancelKeyPress += myHandler;

void myHandler(object sender, ConsoleCancelEventArgs args)
{
    // do something to cancel/interrupt your jobs/tasks/threads
}

This event is raised when user presses Ctrl+C or Break keys. IIRC, the event is invoked asynchronously from the Main() thread, so you will get it even if your "Main" function wandered deep into some other code and is grinding something.

I mean, if your main thread sleeps in Task.WaitAll, you will still get that event if keys are pressed.

Another thing is, how to cancel your tasks. That depends on how your long running tasks are organized. Probably CancellationTokenSource will be your friend if you use Tasks, Threads or some your own things. Tasks support CancellationTokens/Source. You can pass the token as one of arguments to the Factory or Task.Run or similar task-creating methods. However, you also need to ensure that the token.ThrowIfCancellationRequested() is used in the tasks' inner code. If you use some libraries to work for you, they may happen to not support CancellationToken, then you will need to research how to cancel/interrupt them properly.

quetzalcoatl
  • 32,194
  • 8
  • 68
  • 107