Search code examples
c#wpfwindow

Application.Startup event limitations (bug?)


It says, I can use Startup event for many things, like initialization, creating multiple forms, blablabla.

However, try to create a new WPF application and add this event handler:

    private void App_Startup(object sender, StartupEventArgs e)
    {
        Window window = new Window();
    }

And after closing main window your application will hang up in the memory. Pausing executing in VS at that moment will drop ugly crash call stack window with a lot of calls somewhere far away from my source code.

Any thoughts?

P.S.: I need to instantiate all of my windows for self-learning configuration purpose once. Should I use some other place?

Call stack


Let me give a better example (example above is good to reproduce the problem, seems it's hard to understand what I am actually doing). I remove StartupUri and then:

    private void App_Startup(object sender, StartupEventArgs e)
    {
        // un-comment this line to reproduce the problem:
        // Window window = new Window();

        // actual implementation will be
        // Window1 window1 = new Window1();
        // Window2 window2 = new Window2();
        // Window3 window3 = new Window3();
        // Window4 window4 = new Window4();
        // ...

        // start main window as usually
        MainWindow mainWindow = new MainWindow();
        mainWindow.Show();
    }

And why do I need instances of windows (window1, ..2, ..3, ...)? Because their content will be inspected to create a list of controls for which I want to save configuration. Some of these windows will never be shown to the user (to example, if he is not admin), some of them are popups, some are editors, etc. So I do not want to display them. But at any application startup the configuration has to be created and saved. And I am looking now for the place to do so.

Surprisingly, using dedicated event Startup seems have some problems with creating multiple windows but not displaying them. Question is why and how to solve it.


Testing a bit more. Try this code and explain me, why application is closed without showing any window?

    private void App_Startup(object sender, StartupEventArgs e)
    {
        Window window = new Window();
        window.Close(); // closing without opening window

        MainWindow mainWindow = new MainWindow();
        mainWindow.Show();
        //mainWindow = new MainWindow(); // can be un-commented, for absolutely no effect
        mainWindow.Show();
        mainWindow.Show();
        mainWindow.Show();
        mainWindow.Show(); // you will not see mainWindow at all, all Show doing nothing
    }

More questions. What do I do?


Something what works, but smells:

    private void App_Startup(object sender, StartupEventArgs e)
    {
        Window window = new Window();

        MainWindow mainWindow = new MainWindow();
        mainWindow.ShowDialog();
        Shutdown();
    }

Notice, calling ShowDialog (which will make event handler waiting for that window closing) and calling Shutdown right after.

It is still not clear what is the problem in the Startup event handler to create instances of some windows. Any ideas?


Solution

  • I have solution, which seems pretty good to me. Idea is similar to winforms - do everything in the Main.

    This, however, is a bit tricky in wpf (I used this question as a guide):

    • Remove StartupUri from App.xaml;
    • Set App.xaml property Build Action to Page (this sounds strange, but it works for desktop application). This will remove Main method from auto-generated classes (App.g.cs and App.g.i.cs).
    • Add Main method manually into Application:

    .

    public partial class App : Application
    {
    
        [STAThread]
        public static void Main()
        {
            Window window1 = new Window();
            Window window2 = new Window();
            Window window3 = new Window();
            // ...
    
            MainWindow start = new MainWindow();
            start.ShowDialog();
    
            SomeOtherWindow next = new MainWindow();
            next.ShowDialog();
    
        }
    }
    

    Now I can directly control which window to show and when (program flow control), as well as there is no more bug with not-closing application when creating instances of windows without displaying them.

    The suspicious things are this Page setting and that fact, what I do not instantiate Application, nor I call Run(). I do not know yet, if it will be a problem in the future. Would be nice to know it for sure.


    It might be necessary to init application still (to load resources?), then

        [STAThread]
        public static void Main()
        {
            App app = new App();
            app.InitializeComponents();
    
            // ... the rest
            // possibly app.MainWindow = start; or app.MainWindow = next;
            // if only 1 window, then app.Run(new MainWindow());
        }