多執行緒與 CopyRect函數 出現「儲存體空間不足」問題 |
缺席
|
esp_pzj
初階會員 發表:32 回覆:70 積分:40 註冊:2007-02-09 發送簡訊給我 |
<textarea class="delphi" rows="10" cols="60" name="code">unit Get;
interface
uses
Classes,QForms,Graphics,Jpeg,SysUtils,Dialogs;
type
GetPhoto = class(TThread)
private
{ Private declarations }
procedure photo(Picture:String);
protected
procedure Execute; override;
end;
implementation
uses Score, ScoreSystem, Menu;
{ GetPhoto }
procedure GetPhoto.photo(Picture:String);
var
Bmp : TBitmap;
Bmp1 : TBitmap;
Jpg : TJpegImage;
begin
Bmp := TBitmap.Create();
Bmp1 := TBitmap.Create();
Jpg := TJpegImage.Create();
Jpg.LoadFromFile('C:\PHOTO1\' Picture '.jpg'); //開起jpg檔案
Bmp.Assign(Jpg); //轉為bmp檔案
Bmp1.Width:=2650;
Bmp1.Height:=1700;
Bmp1.Canvas.CopyRect(Rect(0,0,Bmp1.Width,Bmp1.Height),Bmp.Canvas,Rect(100,100,Bmp1.Width-100,Bmp1.Height-100));//複製Bmp圖片至Bmp1
//此行會出現問題 儲存體空間不足 無法執行
Bmp1.SaveToFile('C:\PHOTO1\' Picture '.Bmp'); //存儲bmp1檔案
bmp.Free;
jpg.Free;
Bmp1.Free;
end;
procedure GetPhoto.Execute;
var i:Integer;
Picture:String;
begin
for i:=1 to 5 do //從記錄抓取到第幾張試卷 開始抓取
begin
Picture:=IntToStr(i);
photo(Picture);
end;
end;
end.</textarea><br />
呼叫 執行緒 方式如下: Thread1:GetPhoto;//宣告 Thread1:=GetPhoto.Create(False);//建立 Thread1.Priority:=tpNormal; //設定執行權限 Thread1.FreeOnTerminate:=True; //執行緒結束時自動釋放 請教各位前輩: 我使用多執行緒,處理 CopyRect函數來處理圖案時會出現「儲存體空間不足」。 程式碼如上, 狀況如下: 1.每張圖案大小 約 30MB 2.每當處理完一次迴圈,會出現記憶體釋放不完全的問題,大約會被吃掉30MB~60MB左右的記憶。 3.200MB 記憶體 執行 五六次迴圈 後 就會出現「儲存體空間不足」。 4.我也會試過不使用 多執行緒 來處理 就不會出現這個問題。 5.整個系統結束,記憶體 就會 全部 釋放了。 是我那一個細節沒注意到,請各位前輩給於指點。 謝謝各位前輩 PS:附上錯誤狀況畫面及記憶使用狀況畫面
------
學藝不精 謝多多指教 |
shunchia63
高階會員 發表:26 回覆:141 積分:198 註冊:2007-05-22 發送簡訊給我 |
|
esp_pzj
初階會員 發表:32 回覆:70 積分:40 註冊:2007-02-09 發送簡訊給我 |
每次執行時 都以確定 多緒執行完成,不過 Memory 未釋放,我可以強制釋放 Memory嗎? ===================引 用 shunchia63 文 章=================== 不使用多緒? 一次配置一塊Memory?? 使用多緒?? ??????????????????? 多個? Thread?,???? 一次配置一塊Memory???,所以Memory可能會被吃光, 是否先Cehck? Memory 在作?或??例外處理 ?????????????????
------
學藝不精 謝多多指教 |
wameng
版主 發表:31 回覆:1336 積分:1188 註冊:2004-09-16 發送簡訊給我 |
|
esp_pzj
初階會員 發表:32 回覆:70 積分:40 註冊:2007-02-09 發送簡訊給我 |
謝謝wameng 前輩的回覆,請問wameng 前輩:
StretchDraw 有裁剪的功能嗎? 如原圖 0,0,800,800我要裁剪成 10,10,790,790 是裁剪不是縮小? 執行緒我一次只執行一個 沒有同一個時間執行多個? 我執行完後等了 很久 記憶體 還是沒有 釋放 ===================引 用 wameng 文 章=================== 為何不直接用 StretchDraw 少了一個載體(JPG->BMP)。 多出將近三分之一的記憶體。 另外控制執行緒同時執行的最大數量。 不可能有多少就開多少執行緒,再多記憶體也不行。 排隊? 執行緒數量控制。
------
學藝不精 謝多多指教 |
wameng
版主 發表:31 回覆:1336 積分:1188 註冊:2004-09-16 發送簡訊給我 |
|
anyone
中階會員 發表:1 回覆:63 積分:52 註冊:2007-02-12 發送簡訊給我 |
|
esp_pzj
初階會員 發表:32 回覆:70 積分:40 註冊:2007-02-09 發送簡訊給我 |
wameng 前輩 :
不太懂您這句說的意思: 為何不直接用 StretchDraw 少了一個載體(JPG->BMP)。 多出將近三分之一的記憶體。 圖檔為JPG 要先轉為BMP 才有辦法做裁剪(Canvas.CopyRect)的動作。 我的疑惑是: 1.Bmp : TBitmap;可以直接開起 JPG檔嗎? 2.還是 Jpg : TJpegImage;可以做裁剪(Canvas.StretchDraw或Canvas.CopyRect)的動作。 3.要使用那一個載體(Bmp : TBitmap或Jpg : TJpegImage還是有其他的載體)來處理,才能達到您說的減少一個載體? 在下不太清楚 wameng 前輩 意思,請前輩解惑 謝謝 我把 FreeOnTerminate := True 放在 procedure GetPhoto.Execute;內 ,還是會出現「儲存體空間不足」。 ===================引 用 wameng 文 章=================== FreeOnTerminate := True 請放在 Execute 內,不然不會釋放。 StretchDraw 不能剪裁。 不然自己畫自己,也可以。 你的問題在於Thread 沒有正確釋放。
------
學藝不精 謝多多指教 |
esp_pzj
初階會員 發表:32 回覆:70 積分:40 註冊:2007-02-09 發送簡訊給我 |
|
anyone
中階會員 發表:1 回覆:63 積分:52 註冊:2007-02-12 發送簡訊給我 |
如下的程式碼
程式執行時記憶體使用量為8348K 第一次按Button記憶體使用量為8444K 第二次按記憶體使用量為8472K 之後按了十幾次都跟第二次一樣你試看看吧! <textarea class="delphi" rows="10" cols="60" name="code">procedure TForm1.Button1Click(Sender: TObject); var Thread1:GetPhoto;//宣告 begin Thread1:=GetPhoto.Create(False);//建立 Thread1.Priority:=tpNormal; //設定執行權限 Thread1.FreeOnTerminate:=True; //執行緒結束時自動釋放 while not Thread1.mTerminate do sleep(100); Thread1.Terminate(); end; </textarea> ===================引 用 esp_pzj 文 章=================== anyone 前輩 您執行完程式後,您可以觀查? Windows工作管理員→效能→實體記憶體→可用 的記憶體 確任程式執行完?,再次執行,再次觀查記憶體,一直重覆這個動作,您會發現 可用記憶體越來越少,最後出現儲存體儲存空間不足。 ??????? ???????????????????????????????????????????????????謝謝您 ===================引 用 anyone 文 章=================== photo(Picture:String) photo(i); i是Integer耶!= = 我改成photo(Picture); 能執行完,並沒有你說的問題 我把i改成15也是沒問題耶! |
esp_pzj
初階會員 發表:32 回覆:70 積分:40 註冊:2007-02-09 發送簡訊給我 |
anyone 請問這兩行執行目的是什麼?
not Thread1.mTerminate 的 mTerminate 是什麼意思內?因該沒有 m,我把m拿掉還是不能run。 會出現 「 Operator not applicable to this operand type 」 錯誤訊息 謝謝 ===================引 用 anyone 文 章=================== 如下的程式碼 程式執行時記憶體使用量為8348K? 第一次按Button記憶體使用量為8444K? 第二次按記憶體使用量為8472K? 之後按了十幾次都跟第二次一樣你試看看吧! <textarea class="delphi" rows="10" cols="60" name="code">procedure TForm1.Button1Click(Sender: TObject); var Thread1:GetPhoto;//宣告 begin Thread1:=GetPhoto.Create(False);//建立 Thread1.Priority:=tpNormal;???????????? //設定執行權限 Thread1.FreeOnTerminate:=True; //執行緒結束時自動釋放 while not Thread1.mTerminate do sleep(100); Thread1.Terminate(); end; </textarea>
------
學藝不精 謝多多指教 |
anyone
中階會員 發表:1 回覆:63 積分:52 註冊:2007-02-12 發送簡訊給我 |
喔!抱歉,沒注意到
以下是Get.pas的程式碼: <textarea class="delphi" rows="10" cols="60" name="code">unit Get; interface uses Classes,QForms,Graphics,Jpeg,SysUtils,Dialogs; type GetPhoto = class(TThread) private { Private declarations } procedure photo(Picture:String); protected procedure Execute; override; public mTerminate:Boolean; end; implementation //uses Score, ScoreSystem, Menu; { GetPhoto } procedure GetPhoto.photo(Picture:String); var Bmp : TBitmap; Bmp1 : TBitmap; Jpg : TJpegImage; begin Bmp := TBitmap.Create(); Bmp1 := TBitmap.Create(); Jpg := TJpegImage.Create(); Jpg.LoadFromFile('C:\' Picture '.jpg'); //開起jpg檔案 Bmp.Assign(Jpg); //轉為bmp檔案 Bmp1.Width:=2650; Bmp1.Height:=1700; Bmp1.Canvas.CopyRect(Rect(0,0,Bmp1.Width,Bmp1.Height),Bmp.Canvas,Rect(100,100,Bmp1.Width-100,Bmp1.Height-100));//複製Bmp圖片至Bmp1 //此行會出現問題 儲存體空間不足 無法執行 Bmp1.SaveToFile('C:\' Picture '.Bmp'); //存儲bmp1檔案 bmp.Free; jpg.Free; Bmp1.Free; end; procedure GetPhoto.Execute; var i:Integer; Picture:String; begin Picture:='Picture'; for i:=1 to 15 do //從記錄抓取到第幾張試卷 開始抓取 begin photo(Picture); end; mTerminate:=true; exit; end; end. </textarea> 那兩行只是暫時的測試,依所需者的功能再去做變更 意義在於等待Thread的結束,未結束則sleep(100); sleep多少也依照個人需求而定 等Thread結束時,再將Thread給Terminate Thread就會完全的釋放掉 ===================引 用 esp_pzj 文 章=================== anyone 請問這兩行執行目的是什麼? not?Thread1.mTerminate?的 mTerminate? 是什麼意思內?因該沒有 m,我把m拿掉還是不能run。 會出現????「? Operator not applicable to this operand type 」?錯誤訊息 ?????????????????????????????????????????????謝謝????????? ===================引 用 anyone 文 章=================== 如下的程式碼 程式執行時記憶體使用量為8348K? 第一次按Button記憶體使用量為8444K? 第二次按記憶體使用量為8472K? 之後按了十幾次都跟第二次一樣你試看看吧! <textarea class="delphi" rows="10" cols="60" name="code">procedure TForm1.Button1Click(Sender: TObject); var Thread1:GetPhoto;//宣告 begin Thread1:=GetPhoto.Create(False);//建立 Thread1.Priority:=tpNormal;???????????? //設定執行權限 Thread1.FreeOnTerminate:=True; //執行緒結束時自動釋放 while not Thread1.mTerminate do sleep(100); Thread1.Terminate(); end; </textarea>
編輯記錄
anyone 重新編輯於 2007-08-23 15:39:03, 註解 無‧
|
esp_pzj
初階會員 發表:32 回覆:70 積分:40 註冊:2007-02-09 發送簡訊給我 |
|
anyone
中階會員 發表:1 回覆:63 積分:52 註冊:2007-02-12 發送簡訊給我 |
我試可以,還是要我寄檔案給你?
===================引 用 esp_pzj 文 章=================== 感謝 anyone? wameng?? shunchia63回覆: ??? ?anyone? 您的方法 我還是試不出來,一樣問題還是存在。 ???? 我將程式改為? 當要處理圖檔 用別一支程執行,一樣可以達到我要的目的?。 我還是保留 多執緒的方法,如各位前輩 遇到跟我一樣的問題? 或 找到決解的方式 請提供我意見。 ????????????????????????????????????? ???? 感謝三位前輩的寶貴意見 |
wameng
版主 發表:31 回覆:1336 積分:1188 註冊:2004-09-16 發送簡訊給我 |
Dear esp_pzj
我之所以遲遲未回復,主要認為 若 FreeOnterminate 在Execute 中,絕不會造成無法釋放的問題。 若真無法釋放,可能原因出在沒有 Try ..Finally 因意外導致不釋放資源。 或遭遇到檔案很大,目前記憶體無法處理的情形。 因此若改為 procedure GetPhoto.photo(Picture:String); var Bmp1 : TBitmap; Jpg : TJpegImage; begin Bmp1 := TBitmap.Create(); Try Jpg := TJpegImage.Create(); Try Jpg.LoadFromFile('C:\PHOTO1\' Picture '.jpg'); //開起jpg檔案 Bmp1.Width :=2650; Bmp1.Height :=1700; Bmp1.Canvas.Draw(-100,-100,JPG); DeleteFile('C:\PHOTO1\' Picture '.Bmp'); Bmp1.SaveToFile('C:\PHOTO1\' Picture '.Bmp'); Finally Jpg.Free; end; Finally Bmp1.Free; end; end; 希望有所助益。另原CopyRect 有放大裁減不正確。 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |