Question

It is an old problem which I first encountered when the first firemonkey came out. Now even with XE5 its the same. I can't use TMemo for anything unless each new line is added with a sufficient time delay.

The problem occurs on heavy forms with lots of controls. And if the lines are long enough to be wrapped and contain special characters, the chance increases. If a string contains line breaks then it almost always gets raised.

Doing the same in a form containing only the memo, and the filler thread, doesn't produce any AVs, I think there must be something wrong somewhere else.

The AV originates in TTextSettings, TTextLayout, TText etc.

Legend

TAgStringList : A derived class from TStringlist with logging, conversion to bytes and locking support.

FLogMemo : The visual TMemo.

FDisplayReq : The condition to add log lines into FLogMemo.

BeignRead : inline method to TMREWSync.BeginRead

EndRead : inline method to TMREWync.EndRead

Log Method

procedure TAgStringList.Log
          ( const APrefixes  : Array of String;
            const ALogs      : Array of String;
            const AException : Exception = nil );
var
  I         : NativeInt;
  LogString : String;
begin

  LogString := Format ( '[%s]', [FormatDateTime ( 'hh:mm:ss.zzz', Time )] );

  for I := 0 to Length ( APrefixes ) - 1 do
    LogString := Format ( '%s[%s]', [LogString, APrefixes [I]] );

  if Assigned ( AException ) then
    LogString := Format ( '%s[%s]', [LogString, AException.ClassName] );

  if FDisplayReq then
    FLogMemo.Lines.Add ( LogString );

  Add ( LogString );

  for I := 0 to Length ( ALogs ) - 1 do
  begin
    if FDisplayReq then
      FLogMemo.Lines.Add ( ALogs [I] );
    Add ( ALogs [I] );
  end;

  if Assigned ( AException ) then
  begin

    if FDisplayReq then
      FLogMemo.Lines.Add ( AException.Message );
    Add ( AException.Message );
    Add ( '' );

  end
  else
    Add ( '' );

end;

Log Thread Method

procedure TAgStringList.LogManager;
var
  I        : NativeInt;
  EndIndex : NativeInt;
begin

  BeginRead;
  EndIndex := GetCount - 1;
  if FLogManager.Tag < EndIndex then
  begin

    if Assigned ( FLogMemo ) then
    begin
      FLogMemo.BeginUpdate;
      for I := FLogManager.Tag to EndIndex do
        FLogMemo.Lines.Add ( Strings [I] );
      FLogMemo.EndUpdate;
      FLogManager.Tag := GetCount;
    end;
    SaveToFile ( FLogFileName );

  end;
  EndRead;

end;
Was it helpful?

Solution

All access of UI controls must be executed on the UI thread. You'll need to queue or synchronize UI access code onto that main UI thread.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top