You cannot set FreeOnTerminate to True and call Free on the thread instance. You have to do one or the other, but not both. In this case, your code destroys the stream twice. You should never destroy an object twice and, of course, when the destructor runs a second time, errors occur.
What happens is that nothing happens from the moment the thread is paused until you explicitly release the thread. When you do this, the destructor will resume the thread, waiting for it to complete. This causes Free called again because you set FreeOnTerminate to True . This second call to Free closes the handle. Then you go back to the proc thread and call ExitThread . This does not work because the stream handle is closed.
As Martin points out in a comment, you should not create TThread directly, since the TThread.Execute method is abstract. In addition, you should not use Resume , which is deprecated. Use Start to start the execution of a suspended thread.
Personally, I do not like to use FreeOnTerminate . Using this function destroys a thread in another thread from which it was created. Usually you use it when you want to forget about the instance link. This leaves you unsure whether the thread was destroyed at the end of the process or even it ends and is freed at the end of the process.
If you must use FreeOnTerminate , you need to make sure that you do not call Free after setting FreeOnTerminate to True . Therefore, the obvious solution is to set FreeOnTerminate to True just before calling Start , and then forget about the thread instance. If you have any exceptions, before you are ready to start, you can safely free the thread, since you FreeOnTerminate will still be False at this point.
Thread := TMyThread.Create(True); Try
A more elegant approach would be to move all initialization to the TMyThread constructor. Then the code will look like this:
Thread := TMyThread.Create(True); Thread.FreeOnTerminate := True; Thread.Start; Thread := nil;
David heffernan
source share