TClientDataset 是否無法完全釋放記憶體 |
尚未結案
|
dannynice
一般會員 發表:12 回覆:19 積分:6 註冊:2003-07-25 發送簡訊給我 |
各位先進你們好,小弟使用TClientDataset連接ACESS 資料庫及MSSql資料庫都發生了虛擬記憶太低,程式無法運做的問題,希望各位先進幫幫忙謝謝 連接方式
TADOConnection -> TADODataSet -> TDataSetProvider -> TClientDataSet
使用TIMER 重覆讀取資料庫中的資料做處理,觀看記憶體會不斷的昇高,不知要如何才可以釋放 程式已放入求助區了 謝謝
http://delphi.ktop.com.tw/topic.php?TOPIC_ID=58771
|
Miles
尊榮會員 發表:27 回覆:662 積分:622 註冊:2002-07-12 發送簡訊給我 |
|
dannynice
一般會員 發表:12 回覆:19 積分:6 註冊:2003-07-25 發送簡訊給我 |
|
Miles
尊榮會員 發表:27 回覆:662 積分:622 註冊:2002-07-12 發送簡訊給我 |
Hi dannynice 你好:
我拿了你的程式不段的修改, 發現測出的結果都一樣, 在工作管理員記憶體不段的增加, 這裡提供一篇高手先進們的文章做參考
http://delphi.ktop.com.tw/topic.php?topic_id=52293 最後使用的程式碼
procedure TForm1.Timer1Timer(Sender: TObject); var IDNO,NAME,ADDRESS,TEL,Mobile : string; begin Timer1.Enabled := False; Timer1.Tag := Timer1.Tag 1; Label2.Caption := IntToStr(Timer1.Tag); if Timer1.Tag < 3000 then begin ADODataSet1.Close; ListBox1.Items.Clear; //ADOConnection1.Connected := True; ClientDataSet1.CommandText := 'Select * from FriendData'; ClientDataSet1.Active := True; //ADOConnection1.Connected := False; ClientDataSet1.First; while not ClientDataSet1.Eof do begin Label3.Caption := IntToStr(SizeOf(ListBox1)); Application.ProcessMessages; Sleep(5); Application.ProcessMessages; if EndStr = 1 then begin Close; Exit; end; IDNO := ClientDataSet1.FieldValues['IDNO']; NAME := ClientDataSet1.FieldValues['NAME']; ADDRESS := ClientDataSet1.FieldValues['ADDRESS']; TEL := ClientDataSet1.FieldValues['TEL']; Mobile := ClientDataSet1.FieldValues['Mobile']; ListBox1.Items.Add(IDNO #9 NAME #9 ADDRESS #9 TEL #9 Mobile); ListBox1.ItemIndex := ListBox1.Count-1; ClientDataSet1.Next; end; ClientDataSet1.Close; Timer1.Enabled := True; end else begin Button1.Enabled := True; Timer1.Tag := 0; end; end;記憶體最高有到28M左右, 但都來來回回, 並不會再飆上去, 我只做到第40次Timer 我不是高手, 高手是正在銀幕前微笑的人.
------
我不是高手, 高手是正在銀幕前微笑的人. |
Chance36
版主 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
dannynice 你好
把程式改成如下,可以看到,記憶體幾乎不會往上飆喔!(我測試的結果都在10M上下,因為ListBox的清除及動態增加而上下) procedure TForm1.Timer1Timer(Sender: TObject); var IDNO,NAME,ADDRESS,TEL,Mobile : string; begin Timer1.Enabled := False; Timer1.Tag := Timer1.Tag 1; Label2.Caption := IntToStr(Timer1.Tag); if Timer1.Tag < 3000 then begin ListBox1.Items.Clear; //ADOConnection1.Connected := True; // 三層架構不用管Connection,它會自動處理 ClientDataSet1.CommandText := 'Select * from FriendData'; ClientDataSet1.Active := True; //ADOConnection1.Connected := False; ClientDataSet1.First; while not ClientDataSet1.Eof do begin Application.ProcessMessages; // Sleep(5); // 加快測試的速度 Application.ProcessMessages; if EndStr = 1 then begin Close; Exit; end; { IDNO := ClientDataSet1.FieldValues['IDNO']; NAME := ClientDataSet1.FieldValues['NAME']; ADDRESS := ClientDataSet1.FieldValues['ADDRESS']; TEL := ClientDataSet1.FieldValues['TEL']; Mobile := ClientDataSet1.FieldValues['Mobile']; ListBox1.Items.Add(IDNO #9 NAME #9 ADDRESS #9 TEL #9 Mobile); } // 改成如下方式 ListBox1.Items.Add(ClientDataSet1.FieldByName('IDNO').AsString #9 ClientDataSet1.FieldByName('NAME').AsString #9 ClientDataSet1.FieldByName('ADDRESS').AsString #9 ClientDataSet1.FieldByName('TEL').AsString #9 ClientDataSet1.FieldByName('Mobile').AsString); ListBox1.ItemIndex := ListBox1.Count-1; ClientDataSet1.Next; end; ClientDataSet1.Close; Timer1.Enabled := True; end else begin Button1.Enabled := True; Timer1.Tag := 0; end; end;PS:原理我不是很清楚,應該與記憶的斷離不連續及記憶體的回收機制有關吧;當ListBox 增加一個Item時,原記憶體空間無法連續,所以系統重新配置新的空間給它,並放棄原空間(因為受變數的記憶體配置互相干擾,於是變數及ListBox紛紛重新配置),同時記憶體的回收速度跟不上配置的速度,而造成記憶的上升。 把變數的使用拿掉後,只剩ListBox的記憶體配置問題,當要新增一個Items時,由於原記憶體未被斷離,可以擴充原記憶體空間,所以記憶體的使用就會很有效率了。 _______________________________________ 深藍的魚,祝您好運..........連連 |
dannynice
一般會員 發表:12 回覆:19 積分:6 註冊:2003-07-25 發送簡訊給我 |
Miles 您好 感謝您的回答
因為我的電腦還有其他的程式在跑,由其是SQL server 他把記憶體吃了就不還了所以我的記憶體都會到70幾之後就會發生錯誤了
原本是要在Sql server 上執行的,為了可以貼上求助區所以改成ACESS 讓各位大大可以直接測試 Chance36 感謝您的回答
您好 如果依照您的做法,那如果是宣告成為整體數會有幫助嗎???
因為我必須要將讀出來的值到其他的Thread中處理所以我才會用變數處理,可是我的程式就算宣告成為整體變數,記憶體還是一樣的上昇,不知道是否還有其他的方式可以使用
|
dannynice
一般會員 發表:12 回覆:19 積分:6 註冊:2003-07-25 發送簡訊給我 |
ClientDataSet1.FieldByName('IDNO').AsString
ClientDataSet1.FieldValues['IDNO']
這二種語法不知有何差異,程式改成如下一樣不會佔記憶體 procedure TForm1.Timer1Timer(Sender: TObject);
var
IDNO,NAME,ADDRESS,TEL,Mobile : string;
begin
Timer1.Enabled := False;
Timer1.Tag := Timer1.Tag 1;
Label2.Caption := IntToStr(Timer1.Tag);
if Timer1.Tag < 3000 then begin
ListBox1.Items.Clear;
//ADOConnection1.Connected := True; // 三層架構不用管Connection,它會自動處理
ClientDataSet1.CommandText := 'Select * from FriendData';
ClientDataSet1.Active := True;
//ADOConnection1.Connected := False;
ClientDataSet1.First;
while not ClientDataSet1.Eof do begin
Application.ProcessMessages;
// Sleep(5); // 加快測試的速度
Application.ProcessMessages;
if EndStr = 1 then begin
Close;
Exit;
end;
IDNO := ClientDataSet1.FieldByName('IDNO').AsString;
NAME := ClientDataSet1.FieldByName('NAME').AsString;
ADDRESS := ClientDataSet1.FieldByName('ADDRESS').AsString;
TEL := ClientDataSet1.FieldByName('TEL').AsString;
Mobile := ClientDataSet1.FieldByName('Mobile').AsString;
ListBox1.Items.Add(IDNO #9 NAME #9 ADDRESS #9 TEL #9 Mobile);
// 改成如下方式
{ListBox1.Items.Add(ClientDataSet1.FieldByName('IDNO').AsString #9
ClientDataSet1.FieldByName('NAME').AsString #9
ClientDataSet1.FieldByName('ADDRESS').AsString #9
ClientDataSet1.FieldByName('TEL').AsString #9
ClientDataSet1.FieldByName('Mobile').AsString);
}
ListBox1.ItemIndex := ListBox1.Count-1;
ClientDataSet1.Next;
end;
ClientDataSet1.Close;
Timer1.Enabled := True;
end
else begin
Button1.Enabled := True;
Timer1.Tag := 0;
end;
end;
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |