Before I had refactored my project for DI with Ninject, I had a simple test class with a simple method:
public void TestImport()
{
var functionality = new ImportFunctionality();
functionality.Execute();
}
When I ran this "app" (merely a sandbox WPF client app for integration testing my library), I had the "main" window showing up and clicking a button on that window called this TestImport method, which executed and then I could test and debug my code, and when then main window was closed, the app died right there and VS would exit debug mode. Normal stuff.
Then I refactored the whole thing and implemented dependency injection with Ninject, factories and interfaces all over the code; the TestImport method now looks like this:
public void TestImport()
{
using (var kernel = new StandardKernel())
{
kernel.Load<SecurityNinjectModule>();
kernel.Load<HelpersNinjectModule>();
kernel.Load<ImportFunctionalityNinjectModule>();
var functionality = kernel.Get<IImportFunctionality>();
functionality.Execute();
}
}
Now when I run the WPF sandbox/test app, everything works and that's great, except when the "main" window gets closed, the application does not exit anymore and Visual Studio remains in debug mode. I added the call to Dispose() in the hope to fix it, but no luck; wrapping it in a using block doesn't fix it either.
If I run the sandbox without clicking the button to run the TestImport method, and then close the main window, the app shuts down properly.
This leads me to the Ninject kernel object. Could it be holding on to its resources somehow despite the Dispose() call? Then how do I properly shut down an application that's running Ninject 3.0?
EDIT
If I bring up the debug/windows/threads window, I see all instantiated threads either sleeping or "in a sleep, wait, or join", if not "not available"; a thread by the name of .NET System Events is sleeping, waiting or joining; the main thread is "managed to native transition" as well as a thread called vshost.RunParkingWindow - and this is where I got to Why won't my WPF application close properly after it displays a WinForms dialog?. The answer seems to work given it is accepted, but as @BahriGungor says "Using System.Environment.Exit is a lot like using dynamite to make a door because you didn't want to follow the exit signs". And it doesn't say why this is happening.
The interesting thing is, it doesn't happen consistently: sometimes I can break and step through code and when I "F5" to resume, and then close the main window, it does shut down properly. What's going on?
EDIT 2
The functionality brings up a FileDialog, and if that dialog doesn't return an Excel workbook's filename, the import window doesn't show up. I've narrowed it down to this:
FileDialog doesn't return anything editable) then VS will not exit debug mode after closing the main app window.Your DI should have a composition root where 99% of your DI code lives. Factories should be the 1% case of dependency injection. For WPF that is the onStartup method.
Also I don't see anywhere in your code where you specify a lifetime management part of DI. If you aren't specifying a lifetime management aka Bind<Samurai>().ToSelf().InSingletonScope(); then you may be getting no lifetime management and no disposal. Here's the information on scopes for ninject.
You say you added a call to dispose somewhere along the way, but if you have event listeners set up without weak references there can be a memory leak leading to a lack of disposal.
Finally did you follow the other answer on your linked System.Environment.Exit question?
Check the Application.Current.Windows collection in the debugger to find the offending window. https://stackoverflow.com/a/7349650/57883
Have you tried using other win forms dialogs or just the one to see if it is reproducable?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With