1) create a thread
MsgThread: = TMsgThread. Create (False); // Create and execute a thread
MsgThread: = TMsgThread. Create (True); // The thread is suspended after being created.
Constructor Create (createsu0000ded: Boolean); The createsu0000ded parameter indicates whether to suspend a thread after creation.
(2) If loop execution is not set in the thread and FreeOnTerminate is set to True, the thread will be released after execution.
(3) After a thread ends, call the method of another event:
If Onterminate: = is set to a method, the method will be called before the end of the thread, for example:
Procedure tsendpoint messagethread. Execute;
Var
Bitmap: Tbitamp;
Begin
Bimap: = Tbitmap. create (nil );
OnTerminate: = Threaddone;
End;
Procedure Threaddone (sender: tobject );
Begin
Bimap. Free; // called before Destory
End;
(4) Secure thread exit before the program ends:
If MsgThread <> nil then
Begin
MsgThread. Terminate;
MsgThread. WaitFor;
End;
(5) determine the status of the current thread:
// The following information is from the monopoly forum.
/Determine whether the thread is released
// Return value: 0-released; 1-running; 2-terminated but not released;
// 3-not created or does not exist
Function TFrmMain. CheckThreadFreed (aThread: TThread): Byte;
Var
I: DWord;
IsQuit: Boolean;
Begin
If Assigned (aThread) then
Begin
Isquit: = getexitcodethread (athread. Handle, I );
If isquit then // if the function succeeds, the return value is nonzero.
// If the function fails, the return value is zero.
Begin
If I = still_active then // if the specified thread has not terminated,
// The termination status returned is still_active.
Result: = 1
Else
Result: = 2; // athread is not free, because the execution statement in tthread. Destroy is
End
Else
Result: = 0; // you can use getlasterror to get the error code.
End
Else
Result: = 3;
End;
(6) thread synchronization.
If the thread needs to call the content in VCL (for example, controls in other forms), it needs to synchronize the thread. Thread Synchronization means that the code is handed over to the main thread to run, and each thread runs in a specific period of time in the main thread. In addition, to prevent multiple threads from executing the same code at the same time, you also need to synchronize multiple threads.
The critical section and mutex are used for synchronization, but they have the following differences:
The critical section can only be used within the process, that is to say, it can only be used for synchronization between threads in the process. The mutex can also be used between processes. The time spent in the critical section is very small, and only 10 ~ 15 time slices, and more than 400 mutex are required. The critical zone ends with the termination of the process, and the mutex exists. If you do not use closehandle (), the process will still exist in the system after it is terminated, that is to say, it is a global system object;
The synchronization methods include:
(1) Use a critical area object.
There are two types of critical section objects: trtlcriticalsection and criticalsection.
?? Trtlcriticalsection usage
VaR
Globalvariable: Double;
VaR
Criticalsection: trtlcriticalsection;
Procedure setglobalvariable (value: Double );
Begin
Entercriticalsection (criticalsection); // enter the critical section
Try
Globalvariable: = value;
Finally
Leavecriticalsection (criticalsection); // exit the critical section.
End;
End;
Initialization
Initializecriticalsection (criticalsection); // Initialization
Finalization
Deletecriticalsection (criticalsection); // Delete
End.
?? Criticalsection usage:
VaR criticalsection: tcriticalsection;
Create: criticalsection: = tcriticalsection. Create;
Usage:
Criticalsection. enter;
Try
...
Finally
Criticalsection. leave;
End;
(2) Use mutex
First, create an event object in the main thread:
VaR
Hmutex: thandle = 0;
...
Hmutex: = createmutex (nil, false, nil );
Add the following code to the execute method of the thread:
If waitforsingleobject (hmutex, infinite) = wait_object_0 then
// Do something;
...
Releasemutex (hmutex );
Finally, remember to release the mutex:
CloseHandle (hMutex );
(3) Use semaphores
Unit Unit1;
Interface
Uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;
Type
TForm1 = class (TForm)
Edit1: TEdit;
Button1: TButton;
Procedure FormCreate (Sender: TObject );
Procedure FormDestroy (Sender: TObject );
Procedure Button1Click (Sender: TObject );
Private
{Private declarations}
Public
{Public declarations}
End;
Type
Tmythread = Class (tthread)
Private
Protected
Procedure execute; override;
Public
Constructor create; virtual;
End;
VaR
Form1: tform1;
Hsem: thandle = 0;
Implementation
{$ R *. DFM}
VaR
TICK: integer = 0;
Procedure tmythread. Execute;
VaR
Waitreturn: DWORD;
Begin
Waitreturn: = waitforsingleobject (hsem, infinite );
Form1.edit1. Text: = inttostr (tick );
INC (tick );
Sleep (10 );
ReleaseSemaphore (HSem, 1, Nil)
End;
Constructor TMyThread. Create;
Begin
Inherited Create (False );
FreeOnTerminate: = True;
End;
Procedure TForm1.FormCreate (Sender: TObject );
Begin
HSem: = CreateSemaphore (Nil, 1, 1, Nil );
End;
Procedure TForm1.FormDestroy (Sender: TObject );
Begin
CloseHandle (HSem );
End;
Procedure TForm1.Button1Click (Sender: TObject );
Var
Index: Integer;
Begin
For index: = 0 to 10 do
Begin
TMyThread. Create;
End;
End;
End.
A general synchronization object uses a Mutex object because Mutex has a special feature: When a thread holding an object goes DOWN, the mutex object can be automatically accepted by other threads waiting for this object, other kernel objects are not specific to this function.
In this case, Semaphore is used because Semaphore can provide the upper limit of an active thread, that is, the lMaximumCount parameter. This is the real usefulness of Semaphore.