Thread class in Delphi
Raptor[Mental Studio]
http://mental.mentsu.com
third
After talking about the constructor, let’s look at the destructor:
destructor TThread.Destroy;
begin
if (FThreadID <> 0) and not FFinished then
begin
Terminate;
if FCreateSuspended then
Resume;
WaitFor;
end;
if FHandle <> 0 then CloseHandle(FHandle);
inherited Destroy;
FFatalException.Free;
RemoveThread;
end;
Before the thread object is released, first check whether the thread is still executing. If the thread is still executing (the thread ID is not 0, and the thread end flag is not set), the Terminate process is called to end the thread. The Terminate procedure simply sets the Terminated flag of the thread class, as in the following code:
PRocedure TThread.Terminate;
begin
FTerminated := True;
end;
Therefore, the thread must still continue to execute until it ends normally, rather than terminating the thread immediately. This should be noted.
A little digression here: Many people have asked me how to terminate a thread "immediately" (of course, referring to threads created with TThread). Of course it doesn’t work! The only way to terminate a thread is to let the Execute method complete execution, so generally speaking, if you want your thread to terminate as soon as possible, you must constantly check the Terminated flag in the Execute method within a short period of time so that you can exit in time. This is a very important principle when designing threaded code!
Of course, if you must be able to exit the thread "immediately", then the TThread class is not a good choice, because if you use the API to forcefully terminate the thread, the TThread thread object will eventually be unable to be released correctly, and access Violation will occur when the object is destructed. In this case you can only use API or RTL functions to create threads.
If the thread is in the startup-suspended state, transfer the thread to the running state, and then call WaitFor to wait. Its function is to wait until the thread ends before continuing to execute. The implementation of WaitFor will be explained later.
After the thread ends, close the thread Handle (the Handle exists when a normal thread is created) and release the thread object created by the operating system.
Then call TObject.Destroy to release this object and release the caught exception object, and finally call RemoveThread to reduce the number of threads in the process.
Other aspects regarding Suspend/Resume and thread priority settings are not the focus of this article and will not be discussed again. What will be discussed below are the other two focuses of this article: Synchronize and WaitFor.
But before introducing these two functions, two other thread synchronization technologies need to be introduced: events and critical sections.
Events are different from events in Delphi. In essence, Event is equivalent to a global Boolean variable. It has two assignment operations: Set and Reset, which are equivalent to setting it to True or False. And checking its value is done through WaitFor operation. Corresponding to the Windows platform, there are three API functions: SetEvent, ResetEvent, and WaitForSingleObject (there are several APIs that implement the WaitFor function, this is the simplest one).
These three are primitives, so Event can implement applications in multi-threads that general Boolean variables cannot. The functions of Set and Reset have been mentioned before. Now let’s talk about the function of WaitFor:
The function of WaitFor is to check whether the state of the Event is the Set state (equivalent to True). If so, it returns immediately. If not, it waits for it to change to the Set state. During the waiting period, the thread calling WaitFor is in a suspended state. In addition, WaitFor has a parameter for timeout setting. If this parameter is 0, it does not wait and returns the Event status immediately. If it is INFINITE, it waits infinitely until the Set status occurs. If it is a limited value, it waits for the corresponding number of milliseconds. Then return the status of the Event.
When the Event transitions from the Reset state to the Set state, it wakes up other threads suspended due to the WaitFor event. This is why it is called Event. The so-called "event" refers to "state transition". This "state transition" information can be passed between threads through Events.
Of course, a similar function can also be achieved using a protected (see critical section introduction below) Boolean variable, as long as WaitFor is replaced with a loop of code that checks the Boolean value. Functionally there is no problem at all, but in actual use you will find that such waiting will occupy a lot of CPU resources, reduce system performance, and affect the execution speed of other threads, so it is uneconomical and sometimes even possible There will be problems. So it is not recommended to use it this way.
(to be continued)