You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi应用使用TThread与OmniThreadLibrary出现内存泄漏问题

排查与解决OmniThreadLibrary Parallel.ForEach内存持续增长问题

1. 规范Parallel.ForEach的使用逻辑

OmniThreadLibrary的IOmniParallelLoop是接口类型,依赖Delphi引用计数自动释放,无需手动调用Free。显式释放反而可能破坏引用计数逻辑,正确的使用方式应确保循环执行完成:

var
  loop: IOmniParallelLoop;
begin
  loop := Parallel.ForEach(0, 999).Execute(
    procedure(const value: Integer)
    begin
      Sleep(10); // 模拟业务操作
    end);
  loop.WaitFor; // 等待所有并行任务完成,避免资源未及时回收
end;

2. 排查任务块内的资源泄漏

并行任务块中创建的局部对象、动态数组、Windows句柄等必须手动释放,避免每个任务残留资源:

procedure(const value: Integer)
var
  tempObj: TCustomObject;
  fileHandle: THandle;
begin
  tempObj := TCustomObject.Create;
  fileHandle := CreateFile(...);
  try
    // 业务逻辑代码
  finally
    tempObj.Free;
    if fileHandle <> INVALID_HANDLE_VALUE then
      CloseHandle(fileHandle);
  end;
end;

同时避免在任务块中使用非线程安全的全局对象,若必须使用需加锁保护,防止资源异常占用。

3. 启用OmniThreadLibrary内置泄漏检测

开启OTL自带的内存泄漏日志,直接定位框架层面的泄漏点:

uses
  OtlMemoryLeak;

initialization
  SetMemoryLeakReportFile('OTL_Leaks.log');
  EnableMemoryLeakReporting;

运行测试后查看日志,根据输出的类名和调用栈定位泄漏源。

4. 检查定时线程的生命周期管理

确保TThread线程未出现堆积或未正确终止:

  • 在Execute方法中正确响应Terminated信号:
procedure TMyWorkerThread.Execute;
begin
  while not Terminated do
  begin
    if FTriggerEvent.WaitFor(INFINITE) = wrSignaled then
    begin
      try
        DoParallelProcessing; // 调用含Parallel.ForEach的处理逻辑
      finally
        FTriggerEvent.ResetEvent;
      end;
    end;
  end;
end;
  • 服务停止时,必须调用线程的Terminate方法并等待线程完全结束,防止线程残留占用内存。

5. 优化32位程序的内存分配与碎片

32位程序虚拟内存空间有限,频繁并行任务易产生内存碎片,可通过以下方式优化:

  • 限制OTL线程池大小,避免创建过多线程:
Parallel.TaskConfig.SetThreadPoolSize(4); // 根据CPU核心数设置,默认等于核心数
  • 使用TOmniObjectPool复用业务对象,减少频繁分配释放带来的碎片问题。

6. 极简代码定位问题根源

剥离业务逻辑,仅保留Parallel.ForEach的空任务测试:

procedure DoMinimalTest;
begin
  Parallel.ForEach(0, 999).Execute(
    procedure(const value: Integer)
    begin
      // 空任务,仅测试OTL框架本身
    end);
end;

若此时内存仍增长,建议升级OmniThreadLibrary到最新版本(当前3.07.7存在已知泄漏修复记录);若内存不再增长,逐步添加业务逻辑,定位具体泄漏点。

7. 启用Delphi FastMM泄漏检测

开启Delphi自带的FastMM内存泄漏报告,获取更全面的泄漏信息:

uses
  FastMM4; // 或FastMM5

initialization
  ReportMemoryLeaksOnShutdown := True;

运行VCL测试程序并关闭,根据弹窗的泄漏报告定位未释放的对象。


内容的提问来源于stack exchange,提问作者user2005049

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 03:02:46