全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1027
推到 Plurk!
推到 Facebook!

TClientDataset 是否無法完全釋放記憶體

尚未結案
dannynice
一般會員


發表:12
回覆:19
積分:6
註冊:2003-07-25

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-10-29 15:04:10 IP:211.75.xxx.xxx 未訂閱
各位先進你們好,小弟使用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

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-10-29 20:31:32 IP:220.135.xxx.xxx 未訂閱
Hi dannynice 你好: 記憶體應該是 ListBox1.Items.Add(IDNO #9 NAME #9 ADDRESS #9 TEL #9 Mobile); 吃掉的, 越加越多, 記憶體會越吃越多, 你的Timer1.Tag沒有初始值, 看起來在程式中是沒有作用的Tag會保持在0 我不是高手, 高手是正在銀幕前微笑的人.
------


我不是高手, 高手是正在銀幕前微笑的人.
dannynice
一般會員


發表:12
回覆:19
積分:6
註冊:2003-07-25

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-11-01 10:51:18 IP:211.75.xxx.xxx 未訂閱
Miles 您好 感謝您的回答 Timer1.Tag 是元件的Tag值,內定是O丫 而且每次timer執行都會將ListBox1.Clear;應該不會佔記憶體才對 小弟有試過單單加入資料到ListBox1,最後清除,重覆執行是不會佔用記憶體的 所以問題應該是在 資料庫元件上
Miles
尊榮會員


發表:27
回覆:662
積分:622
註冊:2002-07-12

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-11-01 21:07:37 IP:220.135.xxx.xxx 未訂閱
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

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-11-01 22:12:51 IP:211.20.xxx.xxx 未訂閱
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

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-11-02 11:42:12 IP:211.75.xxx.xxx 未訂閱
Miles 您好 感謝您的回答 因為我的電腦還有其他的程式在跑,由其是SQL server 他把記憶體吃了就不還了所以我的記憶體都會到70幾之後就會發生錯誤了 原本是要在Sql server 上執行的,為了可以貼上求助區所以改成ACESS 讓各位大大可以直接測試 Chance36 感謝您的回答 您好 如果依照您的做法,那如果是宣告成為整體數會有幫助嗎??? 因為我必須要將讀出來的值到其他的Thread中處理所以我才會用變數處理,可是我的程式就算宣告成為整體變數,記憶體還是一樣的上昇,不知道是否還有其他的方式可以使用
dannynice
一般會員


發表:12
回覆:19
積分:6
註冊:2003-07-25

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-11-04 12:43:21 IP:211.75.xxx.xxx 未訂閱
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;
系統時間:2024-07-01 9:18:24
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!