Thread class in Delphi - (5, finale)

zhaozj2021-02-08  202

Thread class in Delphi

Raptor [Mental Studio]

Http://eental.mentsu.com

Five (finale)

Back to the front CheckSynchronize, see the following code: function CheckSynchronize (Timeout: Integer = 0): Boolean; var SyncProc: PSyncProc; LocalSyncList: TList; begin if GetCurrentThreadID <> MainThreadID then raise EThread.CreateResFmt (@SCheckSynchronizeError, [GetCurrentThreadID]) ; if Timeout> 0 then WaitForSyncEvent (Timeout) else ResetSyncEvent; LocalSyncList: = nil; EnterCriticalSection (ThreadLock); try Integer (LocalSyncList): = InterlockedExchange (Integer (SyncList), Integer (LocalSyncList)); try Result: = (LocalSyncList < > nil) and (LocalSyncList.Count> 0); if Result then begin while LocalSyncList.Count> 0 do begin SyncProc: = LocalSyncList [0]; LocalSyncList.Delete (0); LeaveCriticalSection (ThreadLock); try try SyncProc.SyncRec. Fmethod; Except syncproc.syncrec.fsynchronizeException: = acquireexceptionObject; end; finally ENTERCRITICALSECTION (THREADLOCK); END; END (SYNCPROC.SIGNAL); END; End; Finally LocalsyncList.Free; end; finally leavecriticalsection (threadlock); end; end; First, this method must be called in the main thread (as before Message is passed to the main thread), otherwise it will throw an exception. Next, ResetSyncevent (it corresponds to the front setsyncEvent), because WaitforsyncEvent is considered, because only Checksynchronize with parameters only in the Linux version, the Windows version is CHECKSYNCHRONIZE that calls the default parameter 0. It is now possible to see the use of SynClist: it is used to record all unreported synchronization methods. Because the main thread has only one, while the child thread may have a lot, when multiple sub-threads call the synchronization method, the main thread may not be processed, so a list is required to record them.

Here, use a local variable LocalsyncList to exchange synclist, which is also an original language: InterlocKedexchange. Similarly, it is also the use of the critical regions to protect the across SYNCLIST. As long as localsynclist is not empty, the accumulated all synchronization method calls are processed by a loop. Finally, release the processing LocalsyncList and exit the critical area. Treatment to the synchronization method: First, the first synchronization method calls the data from the list (removed and deleted from the list). Then exit the critical region (the reason is of course to prevent deadlocks). Then it is a true call synchronization method. If an exception occurs in the synchronization method, the synchronization method data record will be stored after being captured. After re-entering the critical area, call the STEVENT notification calling thread, and the synchronization method is executed (see WaitforsingleObject call in front synchronize). At this point, the implementation of the entire SYNCHRONIZE is complete.

Finally, Waitfor, its function is to wait for the thread execution to end. Its code is as follows: function TTREAD.WAITFOR: longword; var h: array [0..1] of thandle; WaitResult: cardinal; msg: tmsg; begin h [0]: = fhandle; if getCurrentThreadIdIdIDID = MAINTHREADID THEN BEGIN WAITRESULT: = 0; H [1]: = SyncEvent; repeat {This prevents a potential deadlock if the background thread does a SendMessage to the foreground thread} if WaitResult = WAIT_OBJECT_0 2 then PeekMessage (Msg, 0, 0, 0, PM_NOREMOVE); WaitResult : = MsgWaitForMultipleObjects (2, H, False, 1000, QS_SENDMESSAGE); CheckThreadError (WaitResult <> WAIT_FAILED); if WaitResult = WAIT_OBJECT_0 1 then CheckSynchronize; until WaitResult = WAIT_OBJECT_0; end else WaitForSingleObject (H [0], INFINITE); CheckThreadError (GetExitCodet "; end; if it is not executing Waitfor in the main thread, it is very simple, as long as WaitForsingleObject Waiting to wait for this thread to be Signaled status. If you perform WaitFor in the main thread, it is more troublesome. First, you must add a syncevent in the Handle array, then wait until the thread ends (ie, MsgWaitFormultiPleObjects returns Wait_Object_0, see the description of this API in the MSDN). Processing in the loop waiting: If there is a message, this message is removed by PeekMessage (but does not remove it from the message loop), then call MsgWaitFormultiPleObjects to wait for the thread handle or syncevent to appear Signaled status while listening to the message ( Qs_sendMessage parameters, see the description of this API in MSDN, for details. This API can be used as a WaitforsingleObject that can wait at the same time. If it is SYNCEVENT to be SETEVENT (Returns WAIT_Object_0 1), then call the checksynchronize to process the synchronization method. Why call Waitfor in the main thread to use MSGWAITFORMULTIPLEOBJECTS, instead of WAITFORSINGLEOBJECT wait for threads? Because death locks are prevented.

Since the Synchronize processing synchronization method may be called in the thread function Execute, the synchronization method is performed in the main thread. If you wait with WaitForsingleObject, the main thread is hanged here, the synchronization method cannot be executed, resulting in a thread being hang Then there is a deadlock. There is no such problem with WaitFormultipleObjects. First, its third parameter is false, indicating that only one signle or syncevent can make the main thread to wake up, as for QS_sendMessage because Synchronize is passed through the message to the main thread, so Prevent the message is blocked. Thus, when Synchronize is called in the thread, the main thread will be awakened and handled synchronous calls, and continue to enter the hang wait state after the call is completed until the thread ends. At this point, the analysis of threaded TTHREAD can tell a paragraph, a summary of the previous analysis: 1. Threads of the thread class must end according to the normal mode, that is, the execute is completed, so in it must be in appropriate Where there is enough to judge the Terminated logo and quit in time. If you must "immediately" exit, you cannot use the thread class, and you must use the API or RTL function. 2. For visual VCL access to Synchronize, pass the message to the main thread, by the main thread process. 3. The access of thread sharing data should be protected in a critical area (of course, using Synchronize). 4. Thread communication can be carried out using Event (of course, you can also use suspend / resume). 5. When using multiple threads in multi-threaded applications, be careful to prevent deadlocks. 6, waiting for the thread to end with the waitfor method.

Dec.01-03 (finally continued)

转载请注明原文地址:https://www.9cbs.com/read-2643.html

New Post(0)