I have long needed a solution to something similar to your problem, not so big as but good looking!
The solution however was to use several Thread to solve, as I am not Delphi developer I had to buy a system and pay for its maintenance!
It took me a while to post the answer since I edited this question because I was looking for a contact from an old friend who solved the mentioned problem!
Follow the implementations he made for me!
Unit unt_funcaoLog
type
{Classe responsável pela geração de LOG!}
TGeraLog = Class
private
FCritical : TCriticalSection;
Const C_ARQUIVO = '.\arquivo_log.txt';
{Indica o arquivo em que o LOG será gerado, no caso, no mesmo diretório do executável!}
Class var FInstance : TGeraLog;
{Instância única do objeto!}
Class function GetInstancia: TGeraLog; static;
{Método responsável por instanciar o objeto singleton!}
public
procedure AfterConstruction; override;
procedure BeforeDestruction; override;
procedure GeraLog(Const AReferencia: String; Const AData: TDateTime; Const ATextoLog: String);
{AReferencia..: Referência à Thread chamadora.}
{AData........: Data e Hora da geração do LOG.}
{ATextoLog....: Texto a ser escrito no arquivo de LOG.}
function TryGeraLog(Const AReferencia: String; Const AData: TDateTime; Const ATextoLog: String): Boolean;
{Método que TENTA gerar uma nova linha de LOG!}
{AReferencia..: Referência à Thread chamadora.}
{AData........: Data e Hora da geração do LOG.}
{ATextoLog....: Texto a ser escrito no arquivo de LOG.}
Class property Instancia: TGeraLog read GetInstancia;
{Referência à instância singleton!}
end;
implementation
{ TGeraLog }
procedure TGeraLog.AfterConstruction;
begin
inherited;
DeleteFile(Self.C_ARQUIVO);
Self.FCritical := TCriticalSection.Create;
end;
procedure TGeraLog.BeforeDestruction;
begin
inherited;
Self.FCritical.Free;
end;
procedure TGeraLog.GeraLog(const AReferencia: string; const AData: TDateTime; const ATextoLog: string);
var
_arquivo : TextFile;
sNovaLinha : String;
begin
sNovaLinha := Format('%s|%s|%s', [AReferencia, DateTimeToStr(AData), ATextoLog]);
{Entra na seção crítica!}
Self.FCritical.Enter;
try
AssignFile(_arquivo, Self.C_ARQUIVO);
if (FileExists(Self.C_ARQUIVO)) then
begin
Append(_arquivo);
end
else
begin
Rewrite(_arquivo);
end;
Writeln(_arquivo, sNovaLinha);
CloseFile(_arquivo);
finally
{Sai da seção crítica}
Self.FCritical.Release;
end;
end;
Class function TGeraLog.GetInstancia: TGeraLog;
begin
if not(Assigned(FInstance)) then
begin
FInstance := TGeraLog.Create;
end;
Result := FInstance;
end;
function TGeraLog.TryGeraLog(const AReferencia: String; const AData: TDateTime;
const ATextoLog: String): Boolean;
var
_arquivo : TextFile;
sNovaLinha : String;
begin
sNovaLinha := Format('%s|%s|%s', [AReferencia, DateTimeToStr(AData), ATextoLog]);
{Tenta entrar na seção crítica!}
Result := Self.FCritical.TryEnter;
if (Result = True) then
begin
try
AssignFile(_arquivo, Self.C_ARQUIVO);
if (FileExists(Self.C_ARQUIVO)) then
begin
Append(_arquivo);
end
else
begin
Rewrite(_arquivo);
end;
Writeln(_arquivo, sNovaLinha);
CloseFile(_arquivo);
finally
{Sai da seção crítica}
Self.FCritical.Release;
end;
end;
end;
initialization
finalization
TGeraLog.Instancia.Free;
end.
Unit unt_diversasThreads
type
TDiversaThread = Class(TThread)
private
FReferencia : String;
FDescricaoErro : String;
public
procedure Execute; override;
{Rotina a ser executada pelo Thread que eventualmente gerará uma linha no arquivo de LOG!}
property Referencia: String read FReferencia write FReferencia;
{Referência que será escrito no arquivo de LOG para sabermos de onde veio a linha!}
property DescricaoErro: String read FDescricaoErro;
end;
implementation
{ TDiversasThread }
procedure TDiversaThread.Execute;
var
bGeraLog : Boolean;
begin
inherited;
try
{Loop enquanto o Thread não for finalizado!}
while not (Self.Terminated) do
begin
{Aqui definimos um time para diminuir o consumo de CPU}
Sleep(10);
{Sorteia um número e verifica se o resto da divisão por dois é zero!}
bGeraLog := (Random(1000000) mod 2) = 0;
if (bGeraLog = True) then
begin
{Chama o método de geração de LOG!}
TGeraLog.Instancia.GeraLog(Self.FReferencia, Now, 'O rato roeu a roupa do Rei de Roma');
end;
end;
except
on E: EInOutError do
begin
Self.FDescricaoErro := Format('Erro de I/O #%d - %s', [E.ErrorCode, SysErrorMessage(E.ErrorCode)]);
end;
on E: Exception do
begin
Self.FDescricaoErro := Format('(%s) - %s', [E.ClassName, E.Message]);
end;
end;
end;
end.
I’m recording the log on this call:
TGeraLog.Instancia.GeraLog('QUEM_ENVIOU_LOG', Now, 'TEXTO_QUE_DESEJA');
According to my friend the function Trygeralog is more efficient when there is multiple access to the same file, but as it is not my case I use only Geralog.
You ask Where to start? and then writes that Current answers do not contain enough details.. And the answers are all negative. Perhaps it would be the case that you better direct the question.
– durtto
Just note the date of the Question, then the date that was posted the negative answers, then note the date that offered the reward! Then note that it was edited by Third! Today is 2 days away and there are better answers than before and able to receive the Correct vote! And of the negative, no vote is mine!
– Junior Moreira
The data repository has to be a text file? the System is Desktop, proceeds?
– Intruso
Yes, it should be text, no matter the extension, csv, txt or log whatever! And yes, it’s desktop!
– Junior Moreira