![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Постоянное разбухание памяти, занимаемой программой [D7, WinXP]
EarlVadim © (2006-04-24 12:22:00)Суть такова.
Раз в минуту программа создает массив из потоков с FreeOnTerminate=true. В самих потоках используются
stfl:=TStringList.Create и FileStream :=TFileStream.Create. В равном им количестве присутствуют stfl.free и FileStream.free.
Результат - каждую минуту увеличение памяти на 50-100кБ.
Но что интересно, если программу свернуть в трей (для чего используется компонента TCoolTrayIcon и развернуть, то размер занимаемой памяти резко уменьшается до уровня первоначального запуска программы.
Подскажите где я мог накосорезить?
Сергей М. (2006-04-24 16:05:00) [21]Код никуда не годится.
Оченьмного вопросов к нему.
Радикальной переделки требует практически все.
EarlVadim (2006-04-24 15:46:00) [22]Начать? Ну думаю адо начать с того, что есть.
Очень упрощая код такой..........
MAINUNIT
type
TMainForm = class(TForm)
procedure FormShow(Sender: TObject);
Procedure ReadData(Sender: TObject);
procedure RxTimerEvent1Timer(Sender: TObject);
procedure RxTimerEvent3Timer(Sender: TObject);
private
protected
public
MThr : MyThread;
Thread : array of MyThread;
Labels: array of TsLabel;
MyLabel : TsLabel;
Gauges: array of TsGauge;
MyGauge : TsGauge;
var
MainForm: TMainForm;
implementation
procedure TMainForm.FormShow(Sender: TObject);
var I : integer;
begin
{ HOSTS : integer - читаю из реестра }
setlength(Labels, Hosts);
setlength(Gauges, Hosts);
setlength(Thread, Hosts);
For i:= 0 to HOSTS-1 do begin
MyLabel := TsLabel.Create(self);
........................
Labels[I] := MyLabel;
MyGauge := TsGauge.Create(self);
........................
Gauges[I] := MyGauge;
MThr := MyThread.Create(HostPath[i]); // передаю UNC-путь файла
MThr.Priority := tpLowest;
MThr.FreeOnTerminate := true;
MThr.Resume;
Thread[i]:= MThr;
end;
Procedure TMainForm.ReadData(Sender: TObject);
Var i1 : integer;
Cycle : boolean;
Begin
Cycle:= true;
For i1:= 0 to Hosts-1 do
IF Thread[i1].Ready THEN BEGIN
Gauges[i1].Progress:= Thread[i1].Progress;
Labels[i1].Caption:= 'Имя - '+Thread[i1].Name;
END else Cycle:= false;
// если все потоки отработали, то флаг=true если нет=false
End;
procedure TMainForm.RxTimerEvent1Timer(Sender: TObject);
Var It : integer;
begin
RxTimerEvent1.Enabled:= false;
RxTimerEvent3.Enabled:= true;
For It:= 0 to Hosts-1 do Thread[it].Resume;
end;
procedure TMainForm.RxTimerEvent3Timer(Sender: TObject);
var I1, Ix : integer;
begin
ReadData(Sender);
end;
MyThreadUnit
interface
MyThread = class(TThread)
private
CF : String;
FName : String;
FProg : integer;
FReady : boolean;
FCheck : boolean;
protected
procedure Execute; override;
public
constructor Create(InPar : String);
function GetReady: Boolean;
function GetName: string;
function GetProg: integer;
property Check: Boolean Read FCheck Write FCheck;
property Ready: Boolean Read GetReady;
property Name: string Read GetName;
property Progress: integer Read GetProg;
end;
implementation
constructor MyThread.Create(InPar : String);
begin
CF:= InPar;
FReady:= false;
FCheck:= true;
inherited Create(true);
end;
function MyThread.GetReady: boolean;
begin
Result:= FReady;
end;
function MyThread.GetName: string;
begin
Result:= FName;
end;
function MyThread.GetProg: integer;
begin
Result:= FProg;
end;
procedure MyThread.Execute;
begin
While FCheck do BEGIN
FName:= .....;
FProg:= ......;
FReady:= true;
Suspend;
FReady:= false;
END;
end;
Сергей М. (2006-04-24 14:41:00) [23]
> как связать всех их
На то и существует упомянутый метод синхронизации.
> проблему-то он вряд ли решит
Начни с минимальной "грамотности" - пролблем ощутимо поубавится.
EarlVadim (2006-04-24 14:22:00) [24]боюсь квалификации не хватит, но может попробую. Засада для меня в том,
что все элементы в форме создаются динамически (Labels : array of TLabel и т.д.), потоки тоже. и как связать всех их - сразу как-то теряюсь.
Но в любом случае - это просто более грамотный метод чтения данных потока, а проблему-то он вряд ли решит.
Сергей М. (2006-04-24 14:14:00) [25]Поток отработав возбудит OnTerminate, обработчик которого будет вызван в контексте осн.потока, где при этом можно "переписать" все что угодно - хоть Label.Caption'ы хоть Конституцию
EarlVadim (2006-04-24 14:06:00) [26]Так мне же все-равно писать эти данные в форму... или я чего-то не понимаю.
Я раз в 3 сек. переписываю Label.Caption'ы например, пока все потоки не отработают.
Сергей М. (2006-04-24 13:15:00) [27]
> цикл по таймеру раз в 3000 опрашивает наличие готовых данных
> в property потоков
Таймер-то зачем ? Вместе с suspend'ом/resum'ом ?
Доп.поток в состоянии самизвестить осн.поток о завершении своей функциональной "деятельности". На то есть событие OnTerminate и вирт.метод DoTerminate.
EarlVadim (2006-04-24 13:09:00) [28]
> MemProo
Я искал в сети но я так понял что она не для Винды. Или плохо искал...
может ссылку?
EarlVadim (2006-04-24 13:08:00) [29]цикл по таймеру раз в 3000 опрашивает наличие готовых данных в property потоков. В конце каждого потока - Suspend;
Как только property READY всех потоков будет TRUE, всем потокам передается Resume, тем самым потоки заканчивают своё существование (должны) поскольку они FreeOnTerminate=true.
Игорь Шевченко (2006-04-24 13:06:00) [30]MemProof
Сергей М. (2006-04-24 13:04:00) [31]А что у тебя творится в основном потоке все то время, пока дополнительные что-то там делают в фоне ?
EarlVadim (2006-04-24 13:01:00) [32]нет не используется.
Сергей М. (2006-04-24 12:45:00) [33]Синхронизация (метод TThread.Synchronize) используется ?
EarlVadim (2006-04-24 12:40:00) [34]да я в общем-то не против проект выслать, но это довольно большой код.
Rouse_ (2006-04-24 12:30:00) [35]Нужно код смотреть...