异步附加到delphi中的.txt文件

时间:2014-09-29 12:29:16

标签: delphi asynchronous text-files

我正在尝试运行邮件服务器,我想跟踪登录,连接等事件。我想将这些数据保存在日志.txt文件中。但由于它必须异步完成,我不知道如何锁定当前数据追加的文件,然后将其释放以供下次使用。所以基本上我正在寻求一个名为asyncAppendToFile(fileName : String; textToAppend : String)

的程序的帮助
procedure SMTPServerUserLogin(ASender: TIdSMTPServerContext;
  const AUsername, APassword: String; var VAuthenticated: Boolean);
begin
  asyncAppendToFile(myFile, 'User ' + AUserName + ' attempts a login');  
end; 

1 个答案:

答案 0 :(得分:4)

从一个应用程序中,您可以创建一个队列并将行放在那里。然后对此队列进行线程检查,并按顺序将行写入日志文件。

TWorkerThread = class(TThread)
private
  Killed:boolean;
  ListLock:TRTLCriticalSection;
  Jobs:TStringList;
  JobEvent:TEvent;
protected
  procedure Execute; override;
  procedure DoJob;
public
  constructor Create(CreateSuspended: Boolean);
  destructor Destroy; override;
  procedure AddJob(s:string);
  function  JobCount: Integer;
  procedure Kill;
end;

constructor TWorkerThread.Create(CreateSuspended: Boolean);
begin
  inherited;
  Killed:=false;
  InitializeCriticalSection(ListLock);
  Jobs:=TStringList.Create;
  JobEvent:=TEvent.Create(nil, true, false, 'jobs.event');
end;

destructor TWorkerThread.Destroy;
begin
  Jobs.Free;
  JobEvent.Free;
  DeleteCriticalSection(ListLock);
  inherited;
end;

procedure TWorkerThread.Execute;
begin
  while not Killed or not Self.Terminated do
    begin
      EnterCriticalSection(ListLock);
      if Jobs.Count>0 then
        begin
          LeaveCriticalSection(ListLock);
          DoJob;
        end
      else
        begin
          JobEvent.ResetEvent;
          LeaveCriticalSection(ListLock);
          JobEvent.WaitFor(5000);
        end;
    end;
end;

procedure TWorkerThread.Kill;
begin
  Killed:=true;
  JobEvent.SetEvent;
  Terminate;
end;

procedure TWorkerThread.AddJob(s:string);
begin
  EnterCriticalSection(ListLock);
  try
    Jobs.Add(s);
    JobEvent.SetEvent;
  finally
    LeaveCriticalSection(ListLock);
  end;
end;

procedure TWorkerThread.DoJob;
var f:textfile;
    s:string;

begin
  //Pick the next Job
  EnterCriticalSection(ListLock);
  try
    s:=Jobs[0];
  finally
    LeaveCriticalSection(ListLock);
  end;

  //Do the work
  assignfile (f,'server.log');
  append(f);
  writeln(f,s);
  closefile (f);

  //Delete from queue
  EnterCriticalSection(ListLock);
  try
    Jobs.Delete(0);  
  finally
    LeaveCriticalSection(ListLock);
  end;
end;

表单创建:

Worker:=TWorkerThread.Create(false);
Worker.Priority:=tpLower;

在表单销毁中:

Worker.Kill;
Worker.WaitFor;
Worker.Free;

用法:

procedure SMTPServerUserLogin(ASender: TIdSMTPServerContext;
  const AUsername, APassword: String; var VAuthenticated: Boolean);
begin
  Worker.AddJob('User ' + AUserName + ' attempts a login');
end;