Link to home
Start Free TrialLog in
Avatar of dudup
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 ?
Avatar of kretzschmar
kretzschmar
Flag of Germany image

>So, it can be accessed in the same time.
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 ;-)

ASKER CERTIFIED SOLUTION
Avatar of TheRealLoki
TheRealLoki
Flag of New Zealand image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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(logmessage);
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;

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of dudup
dudup

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.processmessages until it is free.

var
 LogInUse  :Boolean=false;

procedure WriteLog;
begin
 while LogInUse do application.processmessages;
 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.