Van*_*laH 4 memory delphi ram tstringlist tthread
使用的版本: Delphi 7.
我正在开发一个在Virtual ListView上执行简单for循环的程序.数据存储在以下记录中:
type TList=record
Item:Integer;
SubItem1:String;
SubItem2:String;
end;
Run Code Online (Sandbox Code Playgroud)
项目是索引.SubItem1操作的状态(成功与否).SubItem2文件的路径.在对循环加载每个文件,做一些操作,然后保存.操作发生在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.
Run Code Online (Sandbox Code Playgroud)
可能是什么问题呢?
我曾想过,也许创建了太多的线程.如果用户加载了100万个文件,那么最终将创建100万个线程 - 尽管只创建并运行 50个线程.
感谢您的输入.
您在问题中显示的代码中(可能)没有泄漏.
我说可能是因为在此期间引发的异常Execute可能导致泄漏.字符串列表的生命周期应该由finally块保护.
FileStringList:= TStringList.Create;
try
LoadFile;
Synchronize(UpdateStatus);
finally
FileStringList.Free;
end;
Run Code Online (Sandbox Code Playgroud)
也就是说,我希望吞下异常LoadFile意味着你不会泄漏字符串列表.
你说可能创建了数千个线程.每个线程为其堆栈保留内存,默认堆栈大小为1MB.一旦预留了数千个1MB堆栈,就可以轻松耗尽或分割地址空间.
我看到过去由于骑士创造线程而导致的问题.例如,我有一个程序在创建和销毁线程时失败,存在的线程数不超过256个.这是一台16核的机器,有4GB的地址空间.您可能有2GB的地址空间.
虽然你说任何时刻都存在不超过50个线程,但我不确定你怎么能确定它.并非最不重要的,因为你已经设置FreeOnTerminate到True,从而交出了控制自己的线程的寿命.
我的猜测是你的问题与你创建的线程数有关.每个处理器一个线程就足够了.重用你的线程.为小型任务创建和销毁线程的成本很高.
如果这还不足以解决您的问题,那么您将需要显示管理线程生命周期的代码.
最后,我想知道你将从这个应用程序线程中提取多少好处.如果它是IO绑定,则线程版本可能会更慢!
| 归档时间: |
|
| 查看次数: |
2322 次 |
| 最近记录: |