【问题标题】:Access Violation when adding multiple lines in a TMemo在 TMemo 中添加多行时访问冲突
【发布时间】:2014-03-27 16:23:56
【问题描述】:

这是我在第一个firemonkey出来时第一次遇到的老问题。现在即使使用 XE5 也一样。除非每条新行都添加足够的时间延迟,否则我不能将 TMemo 用于任何事情。

问题出现在具有大量控件的繁重表单上。如果行长到足以被换行并包含特殊字符,那么机会就会增加。如果一个字符串包含换行符,那么它几乎总是会被引发。

在只包含备忘录和填充线程的表单中执行相同操作不会产生任何 AV,我认为其他地方一定有问题。

AV起源于TTextSettings、TTextLayout、TText等

传说

TAgStringList :TStringlist 的派生类,具有日志记录、转换为字节和锁定支持。

FLogMemo : 视觉 TMemo。

FDisplayReq : 将日志行添加到 FLogMemo 的条件。

BeignRead : TMREWSync.BeginRead 的内联方法

EndRead : TMREWync.EndRead 的内联方法

记录方法

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;

日志线程方法

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;

【问题讨论】:

    标签: multithreading delphi logging firemonkey delphi-xe5


    【解决方案1】:

    所有对 UI 控件的访问都必须在 UI 线程上执行。您需要将 UI 访问代码排队或同步到该主 UI 线程。

    【讨论】:

    • 你能举个小例子来说明我是怎么做到的吗?
    • BeginUpdate 和 EndUpdate 在它们之间有一个“for”,并且根据 Log Method,始终添加至少 2 行。该线程也每秒迭代一次,因此中间总是有 10-20 行。
    • 抱歉,没有发现 for 循环
    • BeginRead 是针对 stringlist 中的列表而不是 FLogmemo
    • 我真的不想再举一个转移到主线程的例子。你一定见过它。那里有无数的例子。许多提供与德尔福。试一试肯定能找到。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-30
    • 2021-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多