0

I don't want to close my C# application when user press Ctrl+C, so I added the following code:

static void Main(string[] args)
{
        // some checks (only one instance running etc.)
        Start(args);
        Console.ReadLine();
}

public static void Start(string[] args)
{
        Console.CancelKeyPress += new ConsoleCancelEventHandler(UserClose);
        // Start infinity timer
        _timer.Interval = 1000;
        _timer.Elapsed += NewRun;
        _timer.AutoReset = true;
        _timer.Start();
}

public static void NewRun(Object sender, System.Timers.ElapsedEventArgs e)
{
        _timer.Stop();
        // Do the run
        _timer.Start();
}

public static void UserClose(object sender, ConsoleCancelEventArgs args)
{

        Console.WriteLine("\nThe read operation has been interrupted.");

        Console.WriteLine("  Key pressed: {0}", args.SpecialKey);

        Console.WriteLine("  Cancel property: {0}", args.Cancel);

        // Set the Cancel property to true to prevent the process from terminating.
        Console.WriteLine("Setting the Cancel property to true...");
        args.Cancel = true;

        // Announce the new value of the Cancel property.
        Console.WriteLine("  Cancel property: {0}", args.Cancel);
        Console.WriteLine("The read operation will resume...\n");
}

But somehow the application always terminate after the UserClose function. How can I debug what my process terminate? And whats wrong with the code above?

UPDATE: Seems that the Main return (like René Vogt mentioned in the comments). But why is the time stopping?

Source: MSDN

ZerOne
  • 1,296
  • 6
  • 20
  • 40
  • 2
    Why do you prevent your program from closing? If user wants to close application, in most cases application must be closed. If you don't want it, probably, you're going wrong way - consider writing service instead of regular application. – Dennis Apr 26 '16 at 10:17
  • 1
    Code works fine here. What is in your `while`? – Patrick Hofman Apr 26 '16 at 10:17
  • Put the breakpoint on the first line of UserCloseMQ, F11 from there – Martheen Apr 26 '16 at 10:18
  • This code works fine for me. Do you see the output of your handler? If so, the problem can only be that your `while` loop exits. If `Main` returns you program will stop. – René Vogt Apr 26 '16 at 10:23
  • Possible duplicate of [How do I use Console.CancelKeyPress in .NET 4? (Works fine in .NET 3.5 and below)](http://stackoverflow.com/questions/2866171/how-do-i-use-console-cancelkeypress-in-net-4-works-fine-in-net-3-5-and-below) – ehh Apr 26 '16 at 10:27
  • @Dennis in the final version I want to send an email before my application exit and for debugging I tried to cancel the Ctrl+C event – ZerOne Apr 26 '16 at 11:57
  • @RenéVogt In fact I dont use a while loop. I use a Timer with an interval, maybe the timer get destroyed in the Ctrl+C event? – ZerOne Apr 26 '16 at 11:58
  • 1
    @ZerOne how should i guess? please post the real code. and as I said, if `Main` returns instead of blocking somehow, your program _will_ terminate no matter what you do. – René Vogt Apr 26 '16 at 12:00
  • @RenéVogt stupid mistake from my side.. the Console.ReadLine keep the application in life, but with the Ctrl+C it seems like the ReadLine finish and so the application returns.. Any ideas how to avoid using ReadLine? – ZerOne Apr 26 '16 at 12:21
  • @ZerOne updated my answer, I'm not sure _why_ it is like that, but Ctrl+C let's `Console.ReadLine()` return with `null`. – René Vogt Apr 26 '16 at 12:25

1 Answers1

1

Your problem is that your program does not wait for anything. It simply terminates.

Here is what is happening in detail:

  • Main is called by the framework
    • Main calls Start
    • Start initializes the _timer
    • the _timer is started
    • Start returns
    • Main returns
  • as Main returned, the framework terminates the process

The _timer is part of your process and is disposed and removed from memory with the proces all together. So after Main returns and the framework removes the process, there is no more timer.


You need to keep Main from returning, maybe like that:

static void Main(string[] args)
{
    // some checks (only one instance running etc.)
    Start(args);
    while (true) Thread.Sleep(10);
}

Note that Console.ReadLine() unfortunatly does not work here, because CtrlC somehow triggers Console.ReadLine() to return null.

René Vogt
  • 43,056
  • 14
  • 77
  • 99
  • Thanks! Just for better understanding: Doesn't Thread.Sleep(10) in a while(true) loop affect the application and waste memory/time? – ZerOne Apr 26 '16 at 12:26
  • @ZerOne it definitly does not feel good and I would only use something like that for debugging purposes. But it does not actually waste something. It's purpose is to keep `Main` from returning and does nothing more than sending the current (main) thread to sleep. So it's not wasting cpu or memory at all (except for a little scheduling which would happen anyway). – René Vogt Apr 26 '16 at 12:28
  • after some investigation I saw this solution (the first one in the question): http://stackoverflow.com/questions/2586612/how-to-keep-a-net-console-app-running – ZerOne Apr 26 '16 at 12:56