Application is still running in memory after Application.Exit() is called

后端 未结 4 1277
不思量自难忘°
不思量自难忘° 2020-12-31 12:19

The application I am building is still running in memory (checked in Task Manager) after it is closed using Application.Exit(). Because of this when I am runnin

相关标签:
4条回答
  • 2020-12-31 12:21

    Because of using Foreground Thread and Lybda Expession thread So, threads which will continue to run until the last foreground thread is terminated. In another way, the application is closed when all the foreground threads are stopped. that's why the application won't wait until the background threads are completed, but it will wait until all the foreground threads are terminated. So In that case we have to explicitly stop the all running threads by using

    Environment.Exit(Environment.ExitCode);

    This kept the memory managed perfectly, with no memory leak.

    0 讨论(0)
  • 2020-12-31 12:25

    It seems that this is a Windows ap and you are calling System.Windows.Forms.Application.Exit() but there is a thread still running in the background. Have you tried

    Application.ExitThread();
    
    Environment.Exit();
    

    You could kill the process as Jonesy mentioned, passing in the process ID of the process if it is a separate application than the current running process.

    For that, you need to use the System.Diagnostics.Process namespace and loop through the currently running processes to get the right pid and then call kill on that pid.

    0 讨论(0)
  • 2020-12-31 12:31

    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 close.

    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

    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.

    0 讨论(0)
  • 2020-12-31 12:33

    One time when I had odd behavior (crashing/freezing during Application.Exit()), I used Process.GetCurrentProcess().CloseMainWindow().

    That function is in the System.Diagnostics namespace and seems to be better than Kill() since it does not force it to quit the same way.

    0 讨论(0)
提交回复
热议问题