2014-01-29 3 views
1

Я работаю над TLogger класса, каротажного мои журналы приложений в файл ...Delphi xe5 - странное поведение необходима помощь

я должен способ получения журналов из файла в TMemo: 1. назначить TMemo для Затем класс TLogger присваивает True свойство DisplayInMemo, а затем просто вызывает GetLogFromFile(); 2. вызов GetLogsFromFile(); затем Self.Memo1.Text: = TLogger.LogsResult;

Ниже ... Ответил решение работает отлично ... незакомментированной решение работает только каждые 2 нажмите на кнопку 4

procedure TForm1.Button4Click(Sender: TObject); // get log.file to memo 
begin 
    // automatic forwarding logs from File to TMemo - it works! 
    //logger.DisplayMemo := Self.Memo1; 
    //logger.DisplayInMemo := True; 
    //logger.GetLogsFromFile(); 

    // tested - half-automatic method of formwarding logs to TMemo - works every 2 clicks :(
    logger.DisplayInMemo := False; 
    logger.GetLogsFromFile(); 
    Self.Memo1.Text := logger.LogsResult; 
end; 

Всего реализация TLogger:

unit Logger; 

interface 

uses 
    System.IOUtils, System.TypInfo, System.SysUtils, FMX.Forms, FMX.Dialogs, System.Classes, FMX.Graphics, FMX.ExtCtrls, LoggerThread, FMX.Memo; 

type 

    TLogger = class 
    private 
    FileName : String;    // name of file to log 
    FilePath : String;    // path to app/log-file 

    LStringResult : String;   // result of thread log.file reading 
    LLoggerMemo : TMemo;    // copy of memo - place where GetLogsFromFile put results 

    LDisplayInMemo : Boolean;   // bool - if True GetLogsFromFile puts results to DisplayMemo, otherwise waiting in LogsResult 
    NewLoggerThread : TLoggerThread; // thread object - created in Create() 

    procedure GetLogsFromFileThreadTerminateHandler(sender: TObject); 

    public 
    constructor Create(); overload;      // open or create 'development.log' 
    constructor Create(LogFileName : String); overload; // open or create LogFileName for logging 
    destructor Destroy(); overload;      // cleaner of TLogger object 
    // main procedures 
    procedure Log(LogString : String);     // add line to log file 
    procedure GetLogsFromFile();      // get all logs from log file to string 
    // settings, reading results, 
    property DisplayInMemo : Boolean read LDisplayInMemo write LDisplayInMemo; //bool - if True GetLogsFromFile puts results to DisplayMemo, otherwise waiting in LogsResult 
    property LogsResult : String read LStringResult write LStringResult;  //string results after Getters from TLogger usage 
    property DisplayMemo : TMemo read LLoggerMemo write LLoggerMemo;   // sets TMemo where results will be put if DisplayInMemo set to True 
    end; 

implementation 

    constructor TLogger.Create(); 
    begin 
    {$IFDEF Android} 
     FilePath := TPath.GetDownloadsPath + System.SysUtils.PathDelim; 
    {$ELSE} 
     FilePath := ExtractFilePath(ParamStr(0)); 
    {$ENDIF} 
    FileName := 'development.log'; 
    LDisplayInMemo := False; 
    // inherited 
    inherited Create; 
    end; 

    constructor TLogger.Create(LogFileName : String); 
    begin 
    {$IFDEF Android} 
     FilePath := TPath.GetDownloadsPath + System.SysUtils.PathDelim; 
     //TPath.Combine(TPath.GetDocumentsPath,'test.txt'); // to have/\ auto-change 
    {$ELSE} 
     FilePath := ExtractFilePath(ParamStr(0)); 
    {$ENDIF} 
    FileName := LogFileName; 
    LDisplayInMemo := False; 
    // inherited 
    inherited Create; 
    end; 

    destructor TLogger.Destroy(); 
    begin 
    inherited Destroy; 
    end; 

    // adds a sigle line to log file with date time 
    procedure TLogger.Log(LogString : String); 
    begin 
    NewLoggerThread := TLoggerThread.Create(True); 
    NewLoggerThread.FreeOnTerminate := True; 
    NewLoggerThread.Log := LogString;         //log to write - date time then added in execute 
    NewLoggerThread.LoggerInstruction := TLoggerInstruction.liLogToFile; //set instuction for thread - LogToFile 
    NewLoggerThread.FileName := FileName; //file to write 
    NewLoggerThread.FilePath := FilePath; //path to file 

    try 
     NewLoggerThread.Start; 
    except 
     NewLoggerThread.Free(); 
    end; 

    end; 

    // results String with LogFile content 
    procedure TLogger.GetLogsFromFile(); 
    begin 
    NewLoggerThread := TLoggerThread.Create(True); 
    NewLoggerThread.FreeOnTerminate := True; 
    NewLoggerThread.OnTerminate := GetLogsFromFileThreadTerminateHandler; 
    NewLoggerThread.FileName := FileName; //file to write 
    NewLoggerThread.FilePath := FilePath; //path to file 
    NewLoggerThread.LoggerInstruction := TLoggerInstruction.liGetLogsFromFile; //set instuction for thread - GetLogFromFile 

    try 
     NewLoggerThread.Start; 
    except 
     NewLoggerThread.Free(); 
    end; 

    end; 

    procedure TLogger.GetLogsFromFileThreadTerminateHandler(sender: TObject); 
    begin 
    LStringResult := (Sender as TLoggerThread).StringResult; 
    if LDisplayInMemo then 
     LLoggerMemo.Text := (Sender as TLoggerThread).StringResult; 
    end; 

end. 

Как вы можете видеть только разница в том, в LDisplayInMemo: если True TMemo заполняется журналами ... когда False Мне нужно 2 щелчка на кнопке 4, чтобы получить результаты в TMemo ...

procedure TLogger.GetLogsFromFileThreadTerminateHandler(sender: TObject); 
    begin 
    LStringResult := (Sender as TLoggerThread).StringResult; 
    if LDisplayInMemo then 
     LLoggerMemo.Text := (Sender as TLoggerThread).StringResult; 
    end; 

Любые идеи? Честно говоря, я не знаю, в чем причина различий в работе обоих решений :(Я также пробовал ProcessMessages после Self.Memo1.Text: = logger.LogsResult;

ответ

2

Причина, по которой следующий код работает только во второй раз нажмите кнопку, что ваш код на самом деле получить информацию журнала работает в другом потоке ... это асинхронного

logger.DisplayInMemo := False; 
logger.GetLogsFromFile(); 
Self.Memo1.Text := logger.LogsResult; //This line runs AT THE SAME TIME you're getting logs! 

ПРИМЕЧАНИЕ: Вы читаете значение logger.LogsResultперед тем это получает значение f запустите свой LoggerThread.

Когда вы нажмете кнопку во второй раз, поток завершит работу (первый раз), и теперь вы сможете прочитать значение.

Причина, по которой работает ваш раздел комментариев, заключается в том, что вы только присваиваете текст заметки, когда поток завершается, то есть завершает работу.

Смежные вопросы