6

I'm playing a little bit with some C# Winforms/WPF code and just stumbled upon something strange. Let's say I have a code like this:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DoSomething();

        // something more if everything worked okay
    }
}

What puzzles me is that I cannot simply close the application from the method DoSomething before the constructor finishes its job. If anything during the execution of DoSomething fails, I need to close the application immediately; however, it just keeps running, executes the part // something more... and THEN closes, but that's way too late for me.

I have to put the code for closing the form inside the constructor itself with a following return; and then it works, but I don't really find that an acceptable solution. I'm trying to move such validation logic from the constructor to my methods.

I've tried things like:

public void DoSomething()
{
    Close();
}

and

public void DoSomething()
{
    Application.Current.Shutdown();
}

But it doesn't seem to work. Yes, both codes do close the application, but only after a fully finished constructor code.

Why would I need such a thing? Well, because at startup I need to check for various things, like availability of the connection and hardware, validate the user etc, and if anything fails, there's no point of executing more code.

I tried the same principle with Winforms and WPF (hence the tags) — works the same way.

Can anybody provide an explanation or a solution?

jordanz
  • 367
  • 4
  • 12
walther
  • 13,466
  • 5
  • 41
  • 67

7 Answers7

8

Just try using Environment.Exit(-1) in your situation and all will be good.

ADDED: This is the best reference i can get for you.

Difference between Application.Exit vs Application.Shutdown vs Environment.Exit

Application.Exit() is for exiting a windows forms application in a graceful way. Basically, it stops the message pump, closes all windows and lands you back in the Main() method just after the call to Application.Run(). However, sometimes it doesn't appear to work - this is usually because there are other foreground threads (apart from the UI thread) still running which are preventing the thread from ending.

Application.Shutdown() is (broadly) the equivalent of Application.Exit() in a WPF application. However, you have a bit more control as you can set the ShutDownMode so that the application shuts down when the main window closes, the last window closes or only when this method is called.

Environment.Exit() kills all running threads and the process itself stone dead. This should only be used in WF or WPF as a last resort when the more graceful methods are not working for some reason. It can also be used to make an abrupt exit from a console application.

Another Reference: How to properly exit a C# application?

Community
  • 1
  • 1
Furqan Safdar
  • 16,260
  • 13
  • 59
  • 93
  • Thanks, this seems to behave as expected. Can you explain, why it doesn't work with `Shutdown()` or `Close()`? Are there any pitfalls to look for with your solution? – walther Nov 10 '12 at 10:49
  • There are no pitfalls. Instead Environment.Exit core responsibility is to terminates the process and gives the underlying OS the specified exit code. Reference: http://msdn.microsoft.com/en-us/library/system.environment.exit.aspx – Furqan Safdar Nov 10 '12 at 11:15
  • Thank you. There are times I don't need to throw exceptions etc, just a simple "quit". :) – walther Nov 10 '12 at 12:41
  • Nice. +1 for clear and comprehensively graded list of alternatives. – Konrad Viltersten Dec 20 '14 at 13:42
3

You can always ignore your fellow developers and just use Environment.FailFast()

But really - don't. If you have critical things to do, S.A verifying the serial port is connected to the nuclear power plant, just do it prior. There's no rule forcing you to Application.Run(...) as soon as Main() is called.

Community
  • 1
  • 1
avishayp
  • 706
  • 5
  • 9
  • Can you please elaborate, why not to do that? The solution from FSX seems to work, are there any potential problems to be aware of with his approach? `Application.Run` is relevant only to Winforms (or maybe I'm wrong?), but what about WPF? Please, can you show an example in WPF to illustrate your solution, e.g. where would you put the critical boot instructions (checking for opened ports and stuff like that)? Simple example would do. – walther Nov 10 '12 at 10:46
1

There have already been posted viable solutions for your problem.

Just to answer your follow-up question: the reason why methods like Close() and Shutdown() do not immediately exit your application is that both just push messages into the application's message queue. They are only processed after MainWindow's constructor finished and code execution returns to the message processing loop, maybe even after some other still pending messages in the queue have been handled too. On the contrary, methods like Environment.Exit() or Environment.FailFast() are kind of hard-core os functions leading to more or less immediately killing the process.

markus987
  • 301
  • 3
  • 8
  • Thank you for the explanation. Shame I can't select multiple answers. At least +1 for you too :) – walther Nov 10 '12 at 12:42
0

A workaround would be to throw a exception and handle it in application.UnhandledException

DjSol
  • 208
  • 1
  • 11
0

Define an Exception class:

public class InitializationException : Exception
{
    public InitializationException()
    {}

    public InitializationException(string msg)
        : base(msg)
    {}

    public InitializationException(string msg, Exception inner)
        : base(msg, inner)
    {}
}

and change your code like this:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        try
        {
            DoSomething();

            // maybe something more if everything went ok
        }
        catch( InitializationException ex )
        {
            // log the exception
            Close();
        }
    }

    public void DoSomething()
    {
        if (notSomethingOK)
            throw new InitializationException( "Something is not OK and the applicaiton must shutdown." );
    }
}

This is a clean and maintainable solution.

Mohammad Dehghan
  • 17,853
  • 3
  • 55
  • 72
0
System.Windows.Forms.Application.Exit();
Eranga Gamagedara
  • 536
  • 1
  • 3
  • 10
0

Conceptually such things should not be used in class constructors. Constructor is somewhat made for instance initialization with starting state and not the actual things may happen (like exceptions, message boxes, etc).

Don't forget that you can just return; from constructor, if you need to break its execution. This is better tactic (most times you don't need to just shutdown application on error without displaying some text).

There are "window shown", "visibility changed", "loaded" and many other events in C# on Windows/WPF, that you can override virtually or add as an event handler. Initialize your form/app there.

They're normal methods so all works as expected. You can try throwing exceptions that your application entry point (Main function) will just catch and ignore.

For WPF, check this: - https://msdn.microsoft.com/en-us/library/system.windows.forms.application.setunhandledexceptionmode(v=vs.110).aspx.

Croll
  • 3,631
  • 6
  • 30
  • 63