I have build a C# Windows Forms Application with Visual Studio 2010.
Run and close application is done successfully within a short time. The process is not running in Task-Manager. As well the debugging process close. No problem occurs.
But if the Application is running a while the program does not close and still leave running in Task-Manager (I just open the apllication and do nothing else, just wait few hours to reproduce the problem). In Debug mode i have to click on STOP DEBUGGING button to end process.
What can i do to find the rootcause?
A process ends after all of the foreground threads stop.
In a typical Winforms application, there's one main foreground thread - the UI thread. This stops after the main form (the one used in Application.Run) is closed. Check what your Main method is doing afterwards, or just put a breakpoint there to see if the thread successfuly
You might also have some foreground worker thread if you're doing multi-threading. It's your responsibility to ensure they're all stopped. The tricky part is that some of the classes you're using might spin up such threads on their own, without you knowing about it. The first thing to keep in mind is that any object you create that implements IDisposable should actually be disposed. This might take care of the issue. One example that often causes trouble is System.Threading.Timer (or System.Timers.Timer) - if you don't Dispose it, it will keep your application running indefinitely.
To investigate the problem, you can use the thread list in Visual Studio's debugger (Debug -> Windows -> Threads). Run the application, wait as long as needed, close the form and then pause the debugger. The thread list will show all the managed threads in the process. Look at the location on the threads that are running - double-clicking a thread will switch your debugger view to that thread, and you can then see the call stack. This might give you some insight about where that thread came from, and what code it's currently executing (i.e. why it is stuck). You'll probably see a wait there somewhere (unless it's actually doing CPU work); just look at the call stack (Debug -> Windows -> Call Stack) and look for something to identify.
If you checked all the threads, and you can't see anything suspicious in the call stacks, you might have to do a bit of configuration in the debugger. There's two main things you can try - first, in the call stack window, right click and select "Show external code". If that doesn't help, you might have to disable Just My Code (Options -> Debugger), and enable symbol loading for the modules involved. This is a bit more complicated.
If the process is still pending that means you are not disposing your resources properly.
Using Application.Exit() or asking the system to do it Environment.Exit(0) may be logged in the system as an error occurred and you are better to know how to properly close a process than relied on Application.Exit(), if you want to close a thread of your app you have to know how to collect those garbage.
You can re-implement the Dispose method to Dispose services, sockets, streams, almost everything that has a .Dispose available.
public class MyClass: IMyClass, IDisposable
{
private bool _disposed = false;
// ...
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
// dispose your stuff you created in this class
// do the same for other classes
// some examples
/*
_webClient.Dispose();
_connector.DataAvailable -= ConnectorHasDataComing
_socket.Dispose();
_timer.Dispose();
_taskLogs.ForEach(x => {
x.Token.Cancel();
x.Task.Wait();
x.Task.Dispose();
});
*/
}
// dispose native events
_disposed = true;
}
If you use System.Threading.Thread or System.Threading.Tasks.Task or System.IO.MemoryStream (or other kind of Stream - Writer/Reader), and others that requires a CancellationTokenSource. If you created the ressource in the class when you are disposing the class, use the Token.Cancel() method to let it know its parent is being disposed and .Wait() for it before calling .Dispose()
public async Task Run(CancellationTokenSource cancellationTokenSource)
{
// ...
while (Running) {
if (cancellationTokenSource.IsCancellationRequested) return;
// ....
}
// ....
using (var reader = new WaveFileReader(tempFile))
{
reader.Position = 0;
await reader.CopyToAsync(fileWriter,81920, cancellationTokenSource.Token);
}
}
I found my issue using the Diagnostic Tools when my Debug was still pending on something after closing the app.

If you use CPU Usage you can click on Break All and it set a breakpoint.
You can then see profiler and find what are your top functions, you might find out that your form is disposed but you have a Thread or Task that invokes fields on your form.

For my case, I was using a filewriter and I implemented IDisposable in that class but it sometimes was about or actual doing a transfer of data between a filereader and itself using .copyTo so it was pending without throwing an exception.

After clicking on one the events, click on Go to Source code and place a breakpoint, you may see events that your code is stocked on.
Otherwise, you can use in the same tool the tab Memory Usage to take a snapshot and look at the Heap and Objects diff or the tab CPU Usage and look at a recorded Profile. If find my copyTo issue that way.
You can also run your app with Throw on all exceptions

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