views:

194

answers:

5

Hello, I have multithreaded application and I've got a little problem when application ends: I can correctly terminate the thread by calling TThread.Terminate method in Form1.OnDestroy event handler, but the termination does take some time and so I can't free the memory (by TThread.Free method). Unfortunately for some other reason I must have TThread.FreeOnTerminate property set to false, so the thread object isn't destroyed automatically after thread termination.

My question is probably a little silly and I should have known it a long time ago, but is this ok and the thread will be destroyed automatically (since the application just ends), or is it a problem and the memory would be "lost"? Thanks a lot for explanation.

+3  A: 

Your question is not silly or simple - read the MSDN article. All in all, if you want to be on the safe side you are better to wait a background thread to terminate before exiting an application.

Serg
+5  A: 

You should wait for the thread to terminate before you begin the process off shutting down the rest of your application, otherwise shared resources may be freed under the threads feet, possibly leading to a string of access violations. After you have waited for thread termination, then you can free it. In fact, that's what the TThread destructor does for you.

If there are no shared resources, then sure, let it die by itself. Even if the thread terminates after the main thread, all that is required is that all your threads exit for the program to terminate. Any memory associated with the thread's object will just get cleaned up and given back to the OS with everything else.

BUT, be careful! If your thread is taking a while to exit, it can lead to a zombie process sitting there churning away without a GUI. That is why it is very important to check the Terminated flag very often in the thread loop, and exit the thread.

N@

Nat
Your code is needlessly complicated. Ever since the introduction of `TThread` the destructor has called `Terminate` and `WaitFor` itself. A simple `Free` (or `FreeAndNil`) will suffice. If the thread class has an overridden destructor it should call `Terminate` and `WaitFor` itself in it, because it must not destroy fields before the thread proc has ended. Leaving all of this to the users of the thread class is too dangerous.
mghie
True. It's belt and braces... I have had programs hang in the `TThread` destructor because the Thread has terminated, and it tries to terminate it again (waiting for an infinite time for a shutdown that will never happen), hence the code. Maybe I've been catching the thread between the thread terminating and the thread cleanup code being executed.
Nat
Actually, thinking about it, I'll remove the code.
Nat
@Nat thanks for the code you posted here, together with mghie's comment it helped me the most
Ondra C.
No problems... So, is your problem solved?
Nat
A: 

When a process terminates the OS will reclaim all allocated memory and will close all open handles. You don't need to worry about MEMORY*) that leaks in the very special event of shutting down the application. The OS will also close all your open handles**), at least theoretically. All those taken into account, it might be safe for you to simply terminate your thread (using TerminateThread(MyThread.Handle)) from your forms destructor, before killing other shared resources. Ask yourself those questions:

  1. What's the thread doing? Is it safe to terminate it at any time? Example: If the thread is doing any writing to disk, it's unsafe to just kill it, because you might live files on disk in an inconsistant state.
  2. Are you using any resources that aren't automatically freed by Windows? Can't think of an good example here...

If you're on the safe side with both, you can use TerminateThread and not wait for the thread to naturally terminate. A safer approach might a combined approach, maybe you should give the thread a chance to naturally terminate and, if it didn't terminate withing 5 seconds, force-terminate it.

*) I'm talking about memory you can prove only leaks on process termination, like threads you kill without giving them a chance to properly shut down, or global singleton classes you don't free. All other unaccounted memory needs to be tracked down and fixed, because it's an bug.

**) Unfortunately the Windows OS is not bug-free. Example: Anyone that worked with serial devices on the Windows platform knows how easy it is to get the serial-device in a "locked" state, requiring an restart to get it working again. Technically that's also an Handle, end-processing the application that locked it should unlock it.

Cosmin Prund
A: 

The thread will eventually terminate and Windows will clean up any memory left over. However, you might as well just wait for the thread to terminate, because that is exactly what Windows will do anyway. Your application may appear to have shut down because all windows may have been closed/hidden, but the application process won't terminate until all threads have finished...

Marjan Venema
A: 

why you dont increment a variable when creating the thread, and on the destroy event wait until thread finish, decrement the variable, and on applicationterminate just do Application.processmessages ?

why your thread isn't freeonterminate=true ? all shared resources can be handled into a critical section.

best regards,

Radu Barbu