請問關於thread 的問題 |
尚未結案
|
SamSam1230
中階會員 發表:128 回覆:178 積分:65 註冊:2004-12-23 發送簡訊給我 |
我寫了一個tthread 的 class 做的事情很簡單就是一個 for loop 無限的在 main form 的 memo print message, 那我發現那是很吃cpu 的, 應該是for loop 造成, 第二是 main form 也被 hold 住 , 好像當了一樣, 這樣thread 不就沒有發揮了 thread 應有的工能嗎? 想請問大大, 是不是我有什麼沒有注意到
procedure DBHandler.Execute; begin while true do begin mainform.memoptr.Lines.Add('Threading'); end; end; |
yyu10
中階會員 發表:9 回覆:99 積分:96 註冊:2005-02-18 發送簡訊給我 |
DBHandler = class(TThread) protected procedure PrintMsg; .... end; procedure DBHandler.PrintMsg; begin mainform.memoptr.Lines.Add('Threading'); end; procedure DBHandler.Execute; begin while true do begin Synchronize(PrintMsg); // 建议了解一下Synchronize的作用 Sleep(500); // 留点CPU给其它的绪 end; end;_________________________ Programming is a passion |
SamSam1230
中階會員 發表:128 回覆:178 積分:65 註冊:2004-12-23 發送簡訊給我 |
|
yyu10
中階會員 發表:9 回覆:99 積分:96 註冊:2005-02-18 發送簡訊給我 |
试试下面的例子
unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Grids, StdCtrls; type TForm1 = class(TForm) Memo1: TMemo; procedure FormShow(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation type TDBThread = class(TThread) protected procedure PrintMsg; procedure Execute; override; end; var DBThread: TDBThread; {$R *.DFM} { TDBThread } procedure TDBThread.Execute; begin while Not Terminated do begin Synchronize(PrintMsg); Sleep(500); end; end; procedure TDBThread.PrintMsg; begin Form1.Memo1.Lines.Add(TimeToStr(Time) ': Threading'); end; procedure TForm1.FormShow(Sender: TObject); begin DBThread := TDBThread.Create(False); end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin DBThread.Terminate; DBThread.WaitFor; DBThread.Free; end; end._________________________ Programming is a passion |
Stallion
版主 發表:52 回覆:1600 積分:1995 註冊:2004-09-15 發送簡訊給我 |
|
SamSam1230
中階會員 發表:128 回覆:178 積分:65 註冊:2004-12-23 發送簡訊給我 |
unit DataThread; interface uses Classes,Windows,SysUtils,DBTables,BDE,DBCommon,forms,DatabaseModuleUnit,filectrl,DB; type DBHandler = class(TThread) private { Private declarations } fEndProc : TNotifyEvent; fSession : TSession; fDataBase : TDatabase; fDataModule : TDataModule; fTable : TTable; fTable1 : TTable; fFileListBox1: TFileListBox; Success : Boolean; ErrMsg : string; protected procedure DoProc(); procedure MyTerminated( Sender : TObject ); procedure testpro; public constructor Create(EndProc: TNotifyEvent = nil); overload; destructor Destroy; override; procedure Execute; override; published end; implementation procedure DBHandler.Execute; begin while not Terminated do begin try try DoProc; Success := True; except on E:Exception do begin ErrMsg := E.Message; Success := False; end; end; finally Terminate; end; end; end; constructor DBHandler.Create(EndProc: TNotifyEvent = nil); begin FreeOnTerminate := True; OnTerminate := MyTerminated; Success := Success; inherited Create(True); fDataModule:= TDataModule.Create(nil); fSession := TSession.Create(fDataModule); fSession.SessionName := 'ThreadSession' inttostr(Sessions.Count); fDataBase := TDatabase.Create(fDataModule); fDataBase.SessionName := fSession.SessionName; fDataBase.DatabaseName := DatabaseModule.DB_Name; fTable := TTable.Create(fDataModule); fTable.DatabaseName := DatabaseModule.DB_Name; fTable1 := TTable.Create(fDataModule); fTable1.DatabaseName := DatabaseModule.DB_Name; fFileListBox1 := TFileListBox.Create(fDataModule); Priority := tpNormal; fEndProc := EndProc; Resume; end; destructor DBHandler.Destroy(); begin fDataModule.Free(); inherited; end; procedure DBHandler.MyTerminated( Sender : TObject ); begin if Success then begin end else begin end; end; procedure DBHandler.DoProc; begin if (not Terminated) then begin Synchronize(testpro); Sleep(500); end; end; procedure DBHandler.testpro; begin while true do begin CCUForm.memoptr.Lines.Add('Threading'); end; end; end.我的tthread 是獨立的一個unit 另外一個 mainform 的 unit 去 var dbthread : DBHandler 去 excute 另外, 我在 terminate 的時候去 free, thread 不是自己做完就會結束跟 free 嗎?為什麼我還要去控制它supend resume 呢? 因為有一大堆東西要做,所以想把它放到背景去 run 請大大指出我那裡錯了? 謝謝 |
Chance36
版主 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
SamSam1230 你好 試試以下兩個設定
1.降低執行緒的優先順序 constructor DBHandler.Create(EndProc: TNotifyEvent = nil); begin FreeOnTerminate := True; OnTerminate := MyTerminated; Success := Success; inherited Create(True); Priority := tpLowest; // 設為最低優先權 ....... Resume; end; 2.使訊息迴圈有作用 procedure DBHandler.testpro; begin while true do begin CCUForm.memoptr.Lines.Add('Threading'); Application.ProcessMessage; end; end; 參考看看!_______________________________________ 深藍的魚,祝您好運..........連連 |
SamSam1230
中階會員 發表:128 回覆:178 積分:65 註冊:2004-12-23 發送簡訊給我 |
|
hagar
版主 發表:143 回覆:4056 積分:4445 註冊:2002-04-14 發送簡訊給我 |
|
SamSam1230
中階會員 發表:128 回覆:178 積分:65 註冊:2004-12-23 發送簡訊給我 |
回應 hager 大大
我只是用memo來看看要怎樣做thread才確定不會影響到foreground 的 mainform 的運作 我的最終要做的不是要printout message 到memo 啦
因為我有一大堆的Database 的東西要一直動
所以用timer 會令到foreground 的 mainform 好像當掉了一樣
當初我寫了thread 但出來的效果一樣mainform 會像當掉了一樣
所以就有個想法用memo 來看看是不是我寫那裡錯了
但發現我只是printout 一句的message 也會這樣
|
jest0024
高階會員 發表:11 回覆:310 積分:224 註冊:2002-11-24 發送簡訊給我 |
引言:unit DataThread; interface uses Classes,Windows,SysUtils,DBTables,BDE,DBCommon,forms,DatabaseModuleUnit,filectrl,DB; type DBHandler = class(TThread) private { Private declarations } fEndProc : TNotifyEvent; fSession : TSession; fDataBase : TDatabase; fDataModule : TDataModule; fTable : TTable; fTable1 : TTable; fFileListBox1: TFileListBox; Success : Boolean; ErrMsg : string; protected procedure DoProc(); procedure MyTerminated( Sender : TObject ); procedure testpro; public constructor Create(EndProc: TNotifyEvent = nil); overload; destructor Destroy; override; procedure Execute; override; published end; implementation procedure DBHandler.Execute; begin while not Terminated do begin try try DoProc; Success := True; except on E:Exception do begin ErrMsg := E.Message; Success := False; end; end; finally ERR1.finaly的意思是指,不管有沒有發生錯誤都會執行 Terminate; //<---被執行了,所以迴圈只能執行一遍 end; end; end; constructor DBHandler.Create(EndProc: TNotifyEvent = nil); begin FreeOnTerminate := True; OnTerminate := MyTerminated; Success := Success; inherited Create(True); fDataModule:= TDataModule.Create(nil); fSession := TSession.Create(fDataModule); fSession.SessionName := 'ThreadSession' inttostr(Sessions.Count); fDataBase := TDatabase.Create(fDataModule); fDataBase.SessionName := fSession.SessionName; fDataBase.DatabaseName := DatabaseModule.DB_Name; fTable := TTable.Create(fDataModule); fTable.DatabaseName := DatabaseModule.DB_Name; fTable1 := TTable.Create(fDataModule); fTable1.DatabaseName := DatabaseModule.DB_Name; fFileListBox1 := TFileListBox.Create(fDataModule); Priority := tpNormal; fEndProc := EndProc; Resume; end; destructor DBHandler.Destroy(); begin fDataModule.Free(); inherited; end; procedure DBHandler.MyTerminated( Sender : TObject ); begin if Success then begin end else begin end; end; procedure DBHandler.DoProc; begin if (not Terminated) then begin Synchronize(testpro); Sleep(500); end; end; procedure DBHandler.testpro; begin while true do ERR2.這兒是在表格內處理的訊息,不能使用回圈呢 begin CCUForm.memoptr.Lines.Add('Threading'); end; end; end.我的tthread 是獨立的一個unit 另外一個 mainform 的 unit 去 var dbthread : DBHandler 去 excute 另外, 我在 terminate 的時候去 free, thread 不是自己做完就會結束跟 free 嗎?為什麼我還要去控制它supend resume 呢? 因為有一大堆東西要做,所以想把它放到背景去 run 請大大指出我那裡錯了? 謝謝 這樣做完全發揮不了執行緒呢!! 1.建立執行緒 2.開始執行廻圈 3.送訊息給表格 4.表格接到訊息後,執行廻圈 <--完全卡在這兒!! 這樣做法跟在表格內放個廻圈一樣!! 5.送訊邊告訴執行緒,要結束了!!發表人 - jest0024 於 2005/05/04 11:35:45 |
SamSam1230
中階會員 發表:128 回覆:178 積分:65 註冊:2004-12-23 發送簡訊給我 |
|
jest0024
高階會員 發表:11 回覆:310 積分:224 註冊:2002-11-24 發送簡訊給我 |
1.你可以在執行緒裡做無窮回圈的事情.
2.使用Synchronize呼叫VCL元件時,執行時間最好別太長。(容易卡住的地方)
procedure DBHandler.Execute; //執行無窮回圈的地方!! begin while not Terminated do begin try DoProc; Success := True; except on E:Exception do begin ErrMsg := E.Message; Success := False; end; end; end; procedure DBHandler.DoProc; begin if (not Terminated) then begin Synchronize(testpro); //使用Synchronize呼叫VCL時,裡的執行時間別太長呢!! Sleep(500); end; end; procedure DBHandler.testpro; //若這兒執行廻圈不就卡死了?! begin CCUForm.memoptr.Lines.Add('Threading'); end; |
SamSam1230
中階會員 發表:128 回覆:178 積分:65 註冊:2004-12-23 發送簡訊給我 |
|
jest0024
高階會員 發表:11 回覆:310 積分:224 註冊:2002-11-24 發送簡訊給我 |
引言: jest0024 大大你的方法 yyu10大大已經提供過 我也try 過, 但都不行.首先,你key的源碼基本上就已經會導致程式無法回應。 若你已經試過yyu10的方法而得不到結果,我想你得一步一步去查證你的問題出在哪兒了? 1.是否執行緒出了問題~?(寫一個基本的執行緒測試) //很單純的一個廻圈 unit Unit5; interface uses Classes; type TestThread = class(TThread) private { Private declarations } protected procedure Execute; override; procedure TestRun; end; implementation uses Unit1; procedure TestThread.Execute; begin while Not Terminated do Synchronize(TestRun); end; procedure TestThread.TestRun; begin Form1.Memo1.Lines.Add('TEST'); end; end. 2.若1沒問題,則查證是否在廻圈內源碼讓程式無法回應.. Form1.Memo1.Lines.Add('TEST');// <--這行無法動!? 一一查證必得你要的結果.. 3.若還是得不到結果,可上傳問題程式,讓大伙兒幫你解決問題~發表人 - jest0024 於 2005/05/04 19:06:27 |
yyu10
中階會員 發表:9 回覆:99 積分:96 註冊:2005-02-18 發送簡訊給我 |
仅仅是一个猜测. 你是不是在主绪(Form1)中直接呼叫了Execute? 如果是, 将该行代码去掉试试.
athread := DBThread.Create; //保留 athread.Execute; //去掉Execute应该放在宣告的protected部分, TThread.Create会自动呼叫. 有兴趣的话, 可以找classes.pas, 看看ThreadProc和TThread.Create两部分. 發表人 - yyu10 於 2005/05/05 10:32:21 |
SamSam1230
中階會員 發表:128 回覆:178 積分:65 註冊:2004-12-23 發送簡訊給我 |
引言: 仅仅是一个猜测. 你是不是在主绪(Form1)中直接呼叫了Execute? 如果是, 将该行代码去掉试试.是呀athread := DBThread.Create; //保留 athread.Execute; //去掉_________________________ Programming is a passion DBThread := DBHandler.Create(button1click); DBThread.Execute();不是這樣用的嗎??? 哎呀... 那把DBThread.Execute(); 拿掉 真的拿掉就好了 但實在不明白, 請問有大大可以講解一下嗎? execute 那要來做什麼? 是不是create 之後就會自動的執行? |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |