Why does Environment.Exit() not terminate the program any more?
I contacted Microsoft about this problem and that seemed to have paid off. At least I'd like to think it did :). Although I didn't get a confirmation of a resolution back from them, the Windows group is difficult to contact directly and I had to use an intermediary.
An update delivered through Windows Update solved the problem. The noticeable 2 second delay before the crash is no longer present, strongly suggesting that the IsWindow() deadlock got solved. And the program shuts down cleanly and reliably. The update installed patches for Windows Defender, wdboot.sys, wdfilter.sys, tcpip.sys, rpcrt4.dll, uxtheme.dll, crypt32.dll and wintrust.dll
Uxtheme.dll is the odd-duck out. It implements the Visual Styles theming API and is used by this test program. I can't be sure, but my money is on that one as the source of the problem. The copy in C:\WINDOWS\system32 has version number 6.2.9200.16660, created on August 14th, 2013 on my machine.
Case closed.
System.Environment.Exit(0) does not exit program
Press any key to continue
Like a comment above said already, this sounds a lot like what your IDE (presumably Visual Studio) would print out once the process has terminated. On my machine, I get this message when I run a console application without attaching the debugger to it, e.g. by starting it with Ctrl+F5. Once I press a key, the console window spawned by Visual Studio will close. This is expected behaviour.
Try running your program with the debugger attached, e.g. by pressing F5. Or start the program from a command prompt instead of starting it from your IDE. The message shouldn't be displayed then.
Note also that if you have a multi-threaded program, and there are non-background threads running, these can keep a process alive even though the main thread has terminated.
Will Environment.Exit(int) kill my application with treads running unmanaged code?
From the official Microsoft documentation, Environment.Exit
:
Terminates this process and returns an exit code to the operating
system.
More usefully, the documentation goes on to state:
- Exit always terminates an application
- Exit terminates an application immediately, even if other threads are running
It sounds like Environment.Exit
is perfectly sufficient for your needs.
What is the difference between Environment.Exit(0) and Environment.Exit(Environment.ExitCode)?
I've used both, and they seem to do the same thing.
As others have already noted, that's because the default value for ExitCode
is 0.
So which one should I use?
Typically, if you call Exit()
, you a) have a good reason for that and b) you want to terminate as soon as possible with all the disadvantages described in the remarks section.
Therefore you would
- never call
Environment.Exit(0);
and instead let thevoid Main()
method run to its end in a normal way. - never call
Environment.Exit(Environment.ExitCode);
because that would imply that the reason for the termination was set a while back. - call
Environment.Exit(ERRORCODE);
, likely with a meaningful constant instead of a magic number
So the real answer is: don't use it at all, if possible.
Instead you might want to try Window.Close()
to close a single window or Application.Exit()
, which closes all windows and gets you back to the Main()
method and out of the Application.Run()
method call.
If that's not sufficient to terminate your program and you still see it in Task Manager, it has a foreground thread running, e.g. a thread that saves the users work. You don't want to terminate that, because it could result in a corrupted file.
There is a concept of a boolean isRunning
or _shouldStop
variable to terminate threads.
If you don't know why your application is not terminating, attach a debugger and have a look at the callstack of the remaining threads.
Why is my c# console application hanging when I try to exit?
My thought based on what you are describing is that the network write operation to \\bbd
is not completing.
If you want to log and exit, but exit is more important than logging, perhaps try something like this:
ThreadPool.QueueUserWorkItem(state => {
Thread.Sleep(2000);
Environment.Exit(0);
});
File.AppendAllText(@"\\bbd\FLog", "Halting: " + DateTime.UtcNow.ToString("dd-MM-yyyy HH:mm:ss") + "\n");
This way, your process will exit in 2 seconds no matter what; even if your log operation never completes.
A more elegant solution might quit as soon as the log operation completes OR after a timeout, but my code is just for an example
Environment.Exit doesn't close
Are you using any threads in the application ?
In case you are, make sure you stop all the threads before exiting the application.
I don't normally prefer the .abort command, but you can try using
th.Abort(); //th is the name of the thread
before you use Environment.Exit(0)
Environment.Exit takes long time to close the application
What's happening behind the scenes is quite clear if you understand how .NET applications work, and how Environment.Exit
works.
In short, Environment.Exit
is not the fastest way to exit an arbitrary application. It still waits for any pending finalizers to run (if they run fast enough, they only have 30 seconds total IIRC). If you're using e.g. sockets, it's perfectly possible that the finalizers take a few seconds to run.
The easiest way to check is of course to use the debugger - just Pause when doing the shutdown, and you'll see which threads are actually executing, and what it is they are executing.
Related Topics
How to Compile a C# File with Roslyn Programmatically
Dynamic Lang. Runtime VS Reflection
The Quest for the Excel Custom Function Tooltip
Escape Button to Close Windows Forms Form in C#
Add a Package with a Local Package File in 'Dotnet'
Directly Sending Keystrokes to Another Process via Hooking
Datetime2' Error When Using Entity Framework in VS 2010 .Net 4.0
How to Get Status Code from Webclient
Accessing All the Nodes in Treeview Control
Multiple Aggregates/Repositories in One Transaction
Record Video of Screen Using .Net Technologies
C# Gui Refresh and Async Serial Port Communication
How to Make an Installer for My C# Application
How to Concatenate Two Ienumerable<T> into a New Ienumerable<T>