MrRoy
MrRoy

Reputation: 1183

Process does not close after closing the form

I have a first form that calls another one and then disappears (frm.visible = false). This form should not come back after being called once, but it's the main form (the first one that appears when you launch the program). I am trying to make it so when you close the second form, both forms close, I have tried multiple things but all of them leave the process active.

This is the code that I use :

private void frmCreation_FormClosing(object sender, FormClosingEventArgs e)
        {
            frmProperties frm = new frmProperties();
            frm.Dispose();
        }
        //I have also tried frm.Close() which also does not work

This code close the two forms, but the process remains active. How do I counter this?

Upvotes: 6

Views: 8261

Answers (3)

jwallet
jwallet

Reputation: 328

I can believe the solution here is : Do not handle it.

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.

enter image description here

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.

enter image description here

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.

enter image description here

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 enter image description here

while disposing make sure no one recalls the form or its instance.

Also, if you are using the form event _FormClosing

Make sure if you have a modal to cancel the form closing, return and set e.Cancel = true; but do not set e.Cancel = true if the form is closing. And do not call this.Close() in a _FormClosing() event that you are handling yourself.

After, you may .Dispose() your stuff, but make sure no Dispose methods call the form back like invoking components, since they are being disposed or already disposed.

For people that use the hack that sets the form in an var instance to have access to it anywhere, do not dispose it, otherwise you are disposing a form already disposed.

Upvotes: 1

logicPwn
logicPwn

Reputation: 103

Application.Exit() tells your App to close itself. Environment.Exit(0) tells Windows to kill it.

I prefer the latter since it really closes your app no matter what.

Upvotes: 8

DarkSquirrel42
DarkSquirrel42

Reputation: 10257

Maybe you are looking for Application.Exit()?

Upvotes: 4

Related Questions