【问题标题】:Reduce memory consumption by delphi application减少delphi应用程序的内存消耗
【发布时间】:2015-06-24 20:39:48
【问题描述】:

我的一个线程系统中有一个接收 html 的 TIdHttp 并用 IHTMLDocument2 处理这个 html 的系统,如下所示:

 if IDocTabela = nil then
    IDocTabela := CreateComObject(Class_HTMLDOcument) as IHTMLDocument2
 else
    IDocTabela.clear;

 IDocTabela.designMode := 'on';
 if IENovo = False then
  while IDocTabela.readyState <> 'complete' do
     Application.ProcessMessages;

 v := VarArrayCreate([0, 0], VarVariant);
 v[0] := xHtml;
 IDocTabela.Write(PSafeArray(System.TVarData(v).VArray));
 IDocTabela.designMode := 'off';
 if IENovo = False then
  while IDocTabela.readyState <> 'complete' do
     Application.ProcessMessages;

 for q := 0 to (IDocTabela.all.tags('TABLE') as IHTMLElementCollection).Length -1 do
    begin
      ovTable := (IDocTabela.all.tags('TABLE') as IHTMLElementCollection).item(q, 0);

      for i := 0 to (ovTable.Rows.Length - 1) do
        begin
          for j := 0 to (ovTable.Rows.Item(i).Cells.Length - 1) do
            begin
              sTemp := TrimRight(TrimLeft(ovTable.Rows.Item(I).Cells.Item(J).InnerText));
              if (sTemp = 'Item') = true then
                 begin
                  bSai := True;
                  Break;
                 end;
            end;
            if bSai = True then
              Break;
        end;
      if bSai = True then
        Break;
    end;

我的问题是这段代码每3秒执行一次,每次执行这段代码,内存消耗增加1.000k,这个应用程序会消耗大量内存并随着时间的推移变慢,直到它锁定,这两行使内存增加的有:

 IDocTabela.Write(PSafeArray(System.TVarData(v).VArray));

ovTable := (IDocTabela.all.tags('TABLE') as IHTMLElementCollection).item(q, 0);

注意:我总是销毁使用 FreeAndNil() 创建的 IHTMLDocument2 组件 知道如何改进此代码,以便停止这种内存消耗吗?

谢谢!

【问题讨论】:

  • 这段代码是在线程中执行的吗? Application.ProcessMessages 不属于这里。
  • 您是否在完全调试模式下使用 FastMM 之类的工具验证了泄漏,或者您是否依赖任务管理器中的数据?
  • 这段代码是在一个线程里面,但是这个过程是在一个线程里面调用的,我是通过任务管理器检查内存的,现在我发现了一个细节,这个问题只有在你有IE 9时才会出现或更高版本,IE 8 没有。用win8 IE11测试了问题,win7 IE11也出现了,win7 64bit,Win XP和Win 7 32bit with IE 8问题没有发生。新版本 IE 的错误?
  • 为什么叫ProcessMessages?我们可以有一个简单的 MCVE 吗?
  • David,application.processmessage 仅在 IE 8 版本中是必需的,因为如果不这样做,文档不会加载,还有其他建议吗?

标签: delphi memory-leaks ihtmldocument2


【解决方案1】:

我总是销毁用 FreeAndNil() 创建的 IHTMLDocument2 组件

你不能那样做。没有IHTMLDocument2 组件。您正在创建实现IHTMLDocument2 接口 的 COM 对象的实例,并且该接口是引用计数的。它的底层实现对象不是基于TObject(因为它一开始就不是用Delphi编写的)。当一个接口的引用计数降至 0 时,它会自动释放其底层对象。只要让变量超出范围即可。如果您必须手动减少引用计数,请将接口设置为nil,而不是使用FreeAndNil()

IDocTabela := CreateComObject(Class_HTMLDOcument) as IHTMLDocument2
...
IDocTabela := nil;

话虽如此,还有另一种方法可以将 HTML 加载到 IHTMLDocument2 中 - 查询 IPersistStreamInit 接口,然后调用其 Load() 方法,该方法将 IStream 作为输入。无需将文档置于设计模式或处理窗口消息。您可以通过将您的 HTML 放入 TStringStreamTMemoryStream 然后将其包装在 TStreamAdapter 中来为您的 HTML 获取 IStream

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-10
    • 2013-06-13
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多