在delphi中异步追加到.txt文件

Vik*_*sov 1 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; 
Run Code Online (Sandbox Code Playgroud)

Fen*_*til 5

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

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;
Run Code Online (Sandbox Code Playgroud)

在表单创建中:

Worker:=TWorkerThread.Create(false);
Worker.Priority:=tpLower;
Run Code Online (Sandbox Code Playgroud)

在表格销毁中:

Worker.Kill;
Worker.WaitFor;
Worker.Free;
Run Code Online (Sandbox Code Playgroud)

用法:

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

  • 在构造函数中首先调用继承是正常的并且首选。你的 Kill 机制只是重新实现 Terminate。更好地利用终止。在 Execute 中调用继承是很奇怪的。你永远不想这样做,即使它没有任何作用,但却引出了这个问题。 (2认同)