In some programming related to multi-threaded, threads often have some messages to be sent to the user interface for display. There are many ways to handle this aspect, and there is a message transfer, global variable, pipeline, etc. A method of combining a global variable is given here. And package the code into a TLOG class, which is convenient to use. Share here and share it.
// TLOG class description section, in fact, the class is a "log queue" const Max_log_len = 1024; type tlog = class private flock: tcriticalsection; // mutually exclusive class, used for thread mutual exclusion // definition log entry cycle queue - Due to the characteristics of the queue, you can save max_log_len-1 log flines: array [0..max_log_len-1] of string; fhead: integer; ftail: integer; // ring queue definition end FMSGHANDLE: THANDLE; // message receiving a window handle FMsgId: integer; // message ID FMsgParam: integer; // message parameter of the log can be used to distinguish objects function GetIsEmpty: boolean; function GetCount: integer; public constructor Create (const MsgHandle: THandle; const MsgId, MsgParam: integer); destructor Destroy; override; procedure Add (const line: string); procedure Gets (lines: TStrings); procedure Clear; property IsEmpty: boolean read GetIsEmpty; property Count: integer read GetCount; end;
// TLOG class implementation
{TLOG}
constructor TLog.Create (const MsgHandle: THandle; const MsgId, MsgParam: integer); begin FHead: = 0; FTail: = 0; FMsgHandle: = MsgHandle; FMsgId: = MsgId; FMsgParam: = MsgParam; FLock: = TCriticalSection.Create ;
DESTRUCTOR TLOG.DESTROY; begin flock.free; inherited;
Procedure Tlog.Add (const line: string); begin flock.enter; try flines [ftail]: = format ('[% s]% s', [formatdatetime ('hh: nn: ss', now), line] ); Ftail: = (ftail 1) mod max_log_len; if fhead = ftail the fhead: = (fhead 1) MOD MAX_LOG_LEN; // If the queue is full, rush down the header data Finally Flock.Leave; End; PostMessage (Fmsghandle , FMSGID, FMSGParam, 0); // Note not using SendMessagend in this point;
Procedure Tlog.gets (LINES: TSTRINGS); Begin Flock.Enter; Try While Ftail <> Fhead Do Begin Lines.Add (FHEAD: = (Fim 1) MOD MAX_LOG_LEN; End; Finally Flock.Leave End; end; procedure tlog.clear; begin flock.enter; try fhead: = 0; ftail: = 0; Finally flock.Leave; end;
Function TLOG.GETCOUNT: INTEGER; begin flock.enter; tryness: = ftail-fhead else result: = ftail max_log_len-fhead; fin or flock.Leave; end; end;
Function Tlog.getisempty: boolean; begin flock.Enter; Try Result: = fhead = ftail; // is empty Finally Flock.Leave; end; end;
Original code: logutils.pas
Use example of TLOG
1. Message definition and processing
Define messages in the main window, as follows CONST CM_MYLOG = WM_USER 101;
TYPE TFORM1 = Class (TFORM) .... Procedure Domylog (Var Msg: TMESSAGE); Message Cm_Mylog; // Message Corresponding .... End;
Message Processing Code Procedure TFORM1.DOMYLOG (VAR MSG: TMESSAGE); VAR LINES: TSTRINGS; Begin IF (msg.wparam = 0) THEN / / Note, 0 Here, the MsgParam that is incorporated when it is established. ISempty the Begin Lines: = TSTRINGLIST.CREATE; TSTRING.GETS (LINES); MEMO1.LINES.ADDSTRINGS (LINES); // Assume that output into MEMO1 finally lines.free; end; end; end; end;
2. TLOG object definition, initialization / release
Define variables in the main window or global; tlog;
Generally generates object procedure tform1.formcreate (Sender: Tobject); recomcate (handle, cm_mylog, 0); // Note, MSGParam = 0 ... End;
Release the object procedure tForm1.formDestroy (Sender: TOBJECT); becomDESTROY (Sender: Tobject); becomd ... flog.free; // Please confirm that the thread is no longer used before the release (or thread has been terminated) ... END;
3. Use TLOG in the thread
... flog.add ('specific log'); // Flog can assign a member variable to the thread when it is created