dudup
asked on
Log file
What is the best method to create a function to write into a text file for multithreaded application ?
I have a text file (log file) called "LOG.TXT" and there are 10 threads writing into it.
So, it can be accessed in the same time.
Anyone have a good code for this kind of task ?
I have a text file (log file) called "LOG.TXT" and there are 10 threads writing into it.
So, it can be accessed in the same time.
Anyone have a good code for this kind of task ?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Another slightly less intensive method is to have your threads do a synchronize for logging, e.g.
type TMythread := class(TThread)
public
mainform: TForm1;
logmessage: string;
procedure SyncLog
.....
...
in the threads execute method
try
... do stuff
except
on e: exception do
begin
logmessage := 'Error: ' + E.Message;
synchronize(SyncLog);
end;
end;
....
...
procedure TMyThread.SyncLog;
begin
MainForm.AddToLog(logmessa ge);
end;
....
procedure TForm1.AddToLog(S: string);
var
TextF:TextFile;
logfilename: string;
begin
logfilename := ChangeFileExt(Paramstr(0), '.log');
assignFile(TextF, logfilename);
try
if FileExists(logfilename) then
append(TextF)
else
Rewrite(TextF);
writeln(TextF, S);
finally
closefile(TextF);
end;
end;
type TMythread := class(TThread)
public
mainform: TForm1;
logmessage: string;
procedure SyncLog
.....
...
in the threads execute method
try
... do stuff
except
on e: exception do
begin
logmessage := 'Error: ' + E.Message;
synchronize(SyncLog);
end;
end;
....
...
procedure TMyThread.SyncLog;
begin
MainForm.AddToLog(logmessa
end;
....
procedure TForm1.AddToLog(S: string);
var
TextF:TextFile;
logfilename: string;
begin
logfilename := ChangeFileExt(Paramstr(0),
assignFile(TextF, logfilename);
try
if FileExists(logfilename) then
append(TextF)
else
Rewrite(TextF);
writeln(TextF, S);
finally
closefile(TextF);
end;
end;
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Which one is less CPU usage ? TCriticalSection or Synchronize ?
cpu usage, i would say TCriticalSection, since it would suspend everything else while in it, but synchronize or postmessage would be the more "correct" way
Isn't it easier if you introduce a global variable to check if the LOG file is in use? If it is in use, then you do an application.processmessage s until it is free.
var
LogInUse :Boolean=false;
procedure WriteLog;
begin
while LogInUse do application.processmessage s;
LogInUse:=true;
// write to the log file
LogInUse:=false;
end;
var
LogInUse :Boolean=false;
procedure WriteLog;
begin
while LogInUse do application.processmessage
LogInUse:=true;
// write to the log file
LogInUse:=false;
end;
See http://www.workshop-alex.org/Sources/Delphi/untExtraInterfaces.html or download http://www.workshop-alex.org/Sources/Delphi/untExtraInterfaces.pas
Look for the functions AssignInterface, combined with GetDebugFile and GetLogFile. Basically, it works a bit like this:
var MyText:TextFile;
begin
AssignInterface(MyText, GetDebugFile('Logfile.txt' ));
// or: AssignInterface(MyText, GetLogFile('Logfile.txt', 'YYYY-MM-DD, HH:NN:SS.ZZZ'));
Rewrite(MyText);
// Write what you like.
CloseFile(MyText);
end;
I wrote these years ago and both are (supposed to be) thread-safe. The DebugFile just generates normal textfiles which I used for debugging. The LogFile is a special textfile format with a timestamp at the beginning of every line, which can be very useful. I've made many improvements on this code recently for Delphi 2006 but am still testing them before I want to share them.
Look for the functions AssignInterface, combined with GetDebugFile and GetLogFile. Basically, it works a bit like this:
var MyText:TextFile;
begin
AssignInterface(MyText, GetDebugFile('Logfile.txt'
// or: AssignInterface(MyText, GetLogFile('Logfile.txt', 'YYYY-MM-DD, HH:NN:SS.ZZZ'));
Rewrite(MyText);
// Write what you like.
CloseFile(MyText);
end;
I wrote these years ago and both are (supposed to be) thread-safe. The DebugFile just generates normal textfiles which I used for debugging. The LogFile is a special textfile format with a timestamp at the beginning of every line, which can be very useful. I've made many improvements on this code recently for Delphi 2006 but am still testing them before I want to share them.
it can't physically, one thread do have already to wait until the file is free for write,
guess you have to try to open the file within a loop until you can open it for write
meikl ;-)