PhantomWhiskers
PhantomWhiskers

Reputation: 218

How do I close a WPF application with multiple windows running on separate threads?

I am working on a WPF application that I need to completely shut down when the main window is closed. There is another window that can be opened by the program that I open and run like this (variable names are changed, but here is the logic):

private void NewWindowButton_Click(object sender, RoutedEventArgs e) {
    Thread WindowThread = new Thread(new ThreadStart(NewWindowThread));
    WindowThread.SetApartmentState(ApartmentState.STA);
    WindowThread.IsBackground = true;
    WindowThread.Start();
}

private void NewWindowThread() {
    var NewWindow = new NewWindow();
    NewWindow.Show();
    Dispatcher.Run();
}

When the main window is closed, I have the closing event call the application shutdown method like this:

private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
    Application.Current.Shutdown();
}

This closes all windows that were created within the same thread as the main window, however this is not closing my other windows that I opened with in new threads. How do I make sure that all of my windows close when the main window closes?

Edit: The linked post only partially answered my question. Using the function Environment.Exit(0); worked for closing every window, but it is causing all of my windows to close about 2-3 seconds after clicking the X button, whereas Application.Current.Shutdown(); closes the windows immediately but leaves the other threads open. There is nothing happening on the same thread after Shutdown gets called so I do not need a return statement after it.

Upvotes: 3

Views: 2634

Answers (2)

Tarrokk
Tarrokk

Reputation: 98

You can change the ShutdownMode in your project properties to shutdown when your MainWindow is closed. In your "Application.xaml" file change

ShutdownMode="OnLastWindowClose"

to

ShutdownMode="OnMainWindowClose"

Upvotes: 4

PhantomWhiskers
PhantomWhiskers

Reputation: 218

I figured out a way to do it myself without having to call Environment.Exit(0); by instead creating a List of Threads, and then called the thread dispatcher's InvokeShutdown method. Here is the modified code from above:

private List<Thread> threadList = new List<Thread>();

private void NewWindowButton_Click(object sender, RoutedEventArgs e) {
    Thread WindowThread = new Thread(new ThreadStart(NewWindowThread));
    threadList.Add(WindowThread);
    WindowThread.SetApartmentState(ApartmentState.STA);
    WindowThread.IsBackground = true;
    WindowThread.Start();
}

private void NewWindowThread() {
    var NewWindow = new NewWindow();
    NewWindow.Show();
    Dispatcher.Run();
}

private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
    foreach (Thread thread in threadList)
    {
        Dispatcher.FromThread(thread).InvokeShutdown();
    }
    Application.Current.Shutdown();
}

This causes all windows in separate threads to close when the main window is closed, and it doesn't cause any delay like Environment.Exit(0); did.

Upvotes: 0

Related Questions