delphi – 没有释放所有内存的TStringList和TThread
使用的版本: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绑定,则线程版本可能会更慢! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |