加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 没有释放所有内存的TStringList和TThread

发布时间:2020-12-15 09:34:07 所属栏目:大数据 来源:网络整理
导读:使用的版本:Delphi 7. 我正在开发一个在Virtual ListView上执行简单for循环的程序.数据存储在以下记录中: type TList=record Item:Integer; SubItem1:String; SubItem2:String;end; 项目是索引. SubItem1操作的状态(成功与否). SubItem2文件的路径. for循
使用的版本:Delphi 7.

我正在开发一个在Virtual ListView上执行简单for循环的程序.数据存储在以下记录中:

type TList=record
  Item:Integer;
  SubItem1:String;
  SubItem2:String;
end;

项目是索引. SubItem1操作的状态(成功与否). SubItem2文件的路径. for循环加载每个文件,执行一些操作然后保存它.操作发生在TStringList中.文件大约每个2mb.

现在,如果我在主窗体上执行操作,它可以完美地工作.

多线程,存在巨大的内存问题.不知何故,TStringList似乎没有被完全释放.在3-4k文件之后,我得到一个EOutofMemory异常.有时,软件会停留在500-600mb,有时则不会.在任何情况下,TStringList始终返回EOutofMemory异常,并且不再可以加载任何文件.在具有更多内存的计算机上,获取异常需要更长时间.

其他组件也会发生同样的事情.例如,如果我使用Synapse的THTTPSend,过了一段时间,软件无法创建任何新线程,因为内存消耗太高.它大概是500-600mb,而它应该是,最大,100mb.在主窗体上,一切正常.

我想这个错误就在我身边.也许我不太了解线程.我试图释放Destroy事件中的所有内容.我尝试过FreeAndNil程序.我一次只尝试一个线程.我尝试手动释放线程(没有FreeOnTerminate ……)

没运气.

所以这是线程代码.这只是基本的想法;不是所有操作的完整代码.如果我删除LoadFile prodecure,一切都很好.根据线程池为每个文件创建一个线程.

unit OperationsFiles;

interface

uses Classes,SysUtils,Windows;

type
 TOperationFile = class(TThread)
 private
  Position : Integer;
  TPath,StatusMessage: String;
  FileStringList: TStringList;
  procedure UpdateStatus;
  procedure LoadFile;
 protected
  procedure Execute; override;
 public
  constructor Create(Path: String; LNumber: Integer);
 end;

implementation

uses Form1;

procedure TOperationFile.LoadFile;
begin
 try
  FileStringList.LoadFromFile(TPath);
  // Operations...
  StatusMessage := 'Success';
 except
  on E : Exception do StatusMessage := E.ClassName;
 end;
end;

constructor TOperationFile.Create(Path : String; LNumber: Integer);
begin
 inherited Create(False);
 TPath := Path;
 Position := LNumber;
 FreeOnTerminate := True;
end;

procedure TOperationFile.UpdateStatus;
begin
 FileList[Position].SubItem1 := StatusMessage;
 Form1.ListView4.UpdateItems(Position,Position);
end;

procedure TOperationFile.Execute;
begin
 FileStringList:= TStringList.Create;
 LoadFile;

 Synchronize(UpdateStatus);

 FileStringList.Free;
end;

end.

可能是什么问题呢?

我曾想过,也许创建了太多的线程.如果用户加载了100万个文件,那么最终将创建100万个线程 – 尽管只创建并运行50个线程.

感谢您的输入.

解决方法

您在问题中显示的代码中(可能)没有泄漏.

我说可能是因为Execute期间引发的异常可能导致泄漏.字符串列表的生命周期应该由finally块保护.

FileStringList:= TStringList.Create;
try
  LoadFile;
  Synchronize(UpdateStatus);
finally
  FileStringList.Free;
end;

也就是说,我希望LoadFile中的异常吞吐意味着你不会泄漏字符串列表.

你说可能创建了数千个线程.每个线程为其堆栈保留内存,默认堆栈大小为1MB.一旦预留了数千个1MB堆栈,就可以轻松耗尽或分割地址空间.

我看到过去由于骑士创造线程而导致的问题.例如,我有一个程序在创建和销毁线程时失败,现有的线程不超过256个.这是一台16核的机器,有4GB的地址空间.您可能有2GB的地址空间.

虽然你说任何时刻都存在不超过50个线程,但我不确定你怎么能确定这一点.尤其是,因为您已将FreeOnTerminate设置为True,从而放弃了对线程生命周期的控制.

我的猜测是你的问题与你创建的线程数有关.每个处理器一个线程就足够了.重用你的线程.为小型任务创建和销毁线程的成本很高.

如果这还不足以解决您的问题,那么您将需要显示管理线程生命周期的代码.

最后,我想知道你将从这个应用程序线程中提取多少好处.如果它是IO绑定,则线程版本可能会更慢!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读