Principle Analysis:
A mutex is a system kernel object that can be owned by each thread and executed by anyone;
After the execution is complete, use the releasemutex function to release the ownership so that other waiting threads can use it.
Other threads can wait in queue using the waitforsingleobject function (waiting can also be understood as queuing application ).
Usage process:
VaRHmutex: thandle;{Declare a global mutex handle first}Createmutex{Create a mutex object}Waitforsingleobject{Waiting in queue with the wait function}Releasemutex{Release ownership}Closehandle{Last released mutex object}
The releasemutex and closehandle parameters are all the handles returned by createmutex. The key is the createmutex function:
FunctionCreatemutex (lpmutexattributes: psecurityattributes; binitialowner: bool;{Whether to allow the creator (in this example, the main thread) to own the mutex object}Lpname: pwidechar{You can give this mutex a name. If not, you can assign a value to nil}): Thandle;{1. The first parameter mentioned earlier. 2. The second parameter must be set to false here. If the main thread has Mutual Exclusion, theoreticallyProgramOther threads have the opportunity to exit. When the value is false, the first thread for execution will first have mutex objects. Once other threads have the mutex object, they must wait. 3. For the third parameter, if a name is given, the function will look for mutex objects with duplicate names from the system. If yes, a handle with the same name will be returned; if the value is nil, a new mutex object will be created directly. In the next example, a name will be created .}
VaR F: integer; {Use this variable to coordinate the output position of each thread} Hmutex: thandle; {Mutex object handle} Function Mythreadfun (P: pointer): DWORD; Stdcall ; VaR I, Y: integer; Begin INC (f); y: = 20 * F; For I: = 0 To 50000 Do Begin If Waitforsingleobject (hmutex, infinite) = wait_object_0 Then Begin Form1.canvas. Lock; form1.canvas. textout ( 20 , Y, inttostr (I); form1.canvas. Unlock; sleep ( 0 ); {A little delayed, or sometimes canvas won't be able to coordinate} Releasemutex (hmutex ); End ; End ; Result: = 0 ; End ; Procedure Tform1.button1click (Sender: tobject ); VaR Threadid: DWORD; Begin Repaint; F: = 0 ; Createthread ( Nil , 0 , @ Mythreadfun, Nil , 0 , Threadid); createthread ( Nil , 0 , @ Mythreadfun, Nil ,0 , Threadid); createthread ( Nil , 0 , @ Mythreadfun, Nil , 0 , Threadid); createthread ( Nil , 0 , @ Mythreadfun, Nil ,0 , Threadid); createthread ( Nil , 0 , @ Mythreadfun, Nil , 0 , Threadid ); End ; Procedure Tform1.formcreate (Sender: tobject ); Begin Hmutex: = createmutex (Nil , False, Nil ); End ; Procedure Tform1.formdestroy (Sender: tobject ); Begin Closehandle (hmutex ); End ;
As the core object of the system, mutex can be cross-process (the critical section won't work). We can use mutex to prevent repeated startup of programs.
Working ideas:
First use openmutex to open a mutex object with a custom name. If it fails to be opened, this object does not exist before;
If you do not have this object before, use createmutex to create one immediately. At this time, the program should be started for the first time;
When you start the service again, the openmutex will have the result, and then force exit.
At the end of the program, use closehandle to release the mutex object.
FunctionOpenmutex (dwdesiredaccess: DWORD;{Open permission}Binherithandle: bool;{Whether it can be inherited by the process created by the current program}Pname: pwidechar{Mutex object name}): Thandle;Stdcall;{The mutex handle is returned successfully; 0 is returned if the mutex handle fails}
Note that the createmutex function here should have a name, because openmutex is required;
In addition, the second parameter of createmutex is no longer important (both true and false), because it is determined by its name.
The program can write as follows:
Unit Unit1; Interface Uses Windows, messages, sysutils, variants, classes, graphics, controls, forms, dialogs; Type Tform1 = Class (Tform) Procedure Formcreate (Sender: tobject ); Procedure Formdestroy (Sender: tobject ); End ; VaR Form1: tform1;Implementation {$ R *. DFM} VaR Hmutex: thandle; Const Namemutex = 'Mymutex' ; Procedure Tform1.formcreate (Sender: tobject ); Begin If Openmutex (mutex_all_access, false, namemutex) <> 0 Then Begin Showmessage ( 'The program started' ); Application. Terminate; End ; Hmutex: = createmutex ( Nil , False, namemutex ); End ; Procedure Tform1.formdestroy (Sender: tobject ); Begin Closehandle (hmutex );End ; End .
This is generally written in the DPR main program, saving some useless execution of the later started program.Code:
Program Project1; Uses Forms, windows, unit1 In 'Unit1. pa' {Form1} ; {$ R *. Res} VaR Hmutex: thandle; Const Namemutex = 'Mymutex' ; Begin {Main thread entry} If Openmutex (mutex_all_access, false, namemutex) <> 0 Then Begin MessageBox (0 , 'The program started' , 'Hup' , Mb_ OK); application. Terminate; End ; Hmutex: = createmutex ( Nil , False, namemutex); application. initialize; application. mainformontaskbar: = true; application. createform (tform1, form1); application. Run; closehandle (hmutex ); {Main thread exit} End .