我正在尝试运行邮件服务器,我想跟踪登录,连接等事件。我想将这些数据保存在日志.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;
答案 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;