程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 支持多線程的日志類,可以在線程中使用,用來與主窗口通訊

支持多線程的日志類,可以在線程中使用,用來與主窗口通訊

編輯:Delphi

  在一些涉及到多線程的程序設計中,線程常常有一些消息要發送到用戶界面進行顯示。這方面處理的方法很多,有通過消息傳遞、全局變量、管道等。這裡給出了一種通過消息傳遞和全局變量相結合的處理的方法。並且把代碼封裝到一個TLog類中,使用方便。在這裡和大家分享。

  //TLog類說明部分,事實上該類是一個“日志隊列”
  const
    MAX_LOG_LEN=1024;
   
  type
    TLog=class
    private
      FLock:TCriticalSection;//互斥類,用於線程互斥訪問
      //定義日志項循環隊列--由於隊列的特性,最多能保存MAX_LOG_LEN-1條日志
      FLines:array [0..MAX_LOG_LEN-1] of string;
      FHead:integer;
      FTail:integer;
      //環隊列定義結束
      FMsgHandle:THandle;//消息接收窗口句柄
      FMsgId:integer;//消息ID
      FMsgParam:integer;//消息參數,可以用來區分不同的日志對象
      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類實現部分

  

  { 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;
  end;

  destructor TLog.Destroy;
  begin
    FLock.Free;
    inherited;
  end;

  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 then FHead:=(FHead+1) mod MAX_LOG_LEN;//如果隊列滿,則沖掉頭部數據
    finally
      FLock.Leave;
    end;
    PostMessage(FMsgHandle,FMsgId,FMsgParam,0);//注意此處未使用SendMessage
  end;

  procedure TLog.Gets(lines: TStrings);
  begin
    FLock.Enter;
    try
      while FTail<>FHead do
      begin
        lines.Add(FLines[FHead]);
        FHead:=(FHead+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;
  end;

  function TLog.GetCount: integer;
  begin
    FLock.Enter;
    try
      if FTail>FHead then
        result:=FTail-FHead
      else
        result:=FTail+MAX_LOG_LEN-FHead;
    finally
      FLock.Leave;
    end;
  end;

  function TLog.GetIsEmpty: boolean;
  begin
    FLock.Enter;
    try
      result:=FHead=FTail;//頭尾重合時為空
    finally
      FLock.Leave;
    end;
  end; 

  原代碼:LogUtils.pas

  

  TLog的使用示例

  1.消息定義和處理

  在主窗口定義消息,如下
  const
    CM_MYLOG=WM_USER+101; 

  type
    TForm1 = class(TForm)
      ....
      procedure DoMyLog(var msg:TMessage);message CM_MYLOG;//消息相應
      ....
    end;

  消息處理代碼
  procedure TForm1.DoMyLog(var msg: TMessage);
  var
    lines:TStrings;
  begin
    if(msg.WParam=0) then//注意,這裡的0與TLog建立時傳入的MsgParam對應
    begin
      if not FLog.IsEmpty then
      begin
        lines:=TStringList.Create;
        try
          FLog.Gets(lines);
          Memo1.Lines.AddStrings(lines);//假設輸出到Memo1中
        finally
          lines.Free;
        end;
      end;
    end;
  end;

  2.TLog對象定義,初始化/釋放

  在主窗口或全局中定義變量
  FLog:TLog;

  一般在窗口建立時生成對象
  procedure TForm1.FormCreate(Sender: TObject);
  begin
    ...
    FLog:=TLog.Create(Handle,CM_MYLOG,0);//注意,這裡的MsgParam=0
    ...
  end;

  在窗口銷毀時釋放對象
  procedure TForm1.FormDestroy(Sender: TObject);
  begin
    ...
    FLog.Free;//注意釋放前請確認線程中已經不再使用(或者線程已經終止)
    ...
  end;

  3.在線程中使用TLog

    ...
    FLog.Add('具體的日志');//FLog可以在線程創建時,賦值給該線程的一個成員變量
  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved