線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2180
推到 Plurk!
推到 Facebook!

請問關於thread 的問題

尚未結案
SamSam1230
中階會員


發表:128
回覆:178
積分:65
註冊:2004-12-23

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-05-03 12:55:39 IP:218.103.xxx.xxx 未訂閱
我寫了一個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

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-05-03 14:25:51 IP:203.14.xxx.xxx 未訂閱
 
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

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-05-03 14:50:16 IP:218.103.xxx.xxx 未訂閱
已經照大大的做法去做 但mainform 還是hold 住 好像當了一樣 請問是什麼問題呢??
yyu10
中階會員


發表:9
回覆:99
積分:96
註冊:2005-02-18

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-05-03 16:14:32 IP:220.245.xxx.xxx 未訂閱
试试下面的例子    
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

發送簡訊給我
#5 引用回覆 回覆 發表時間:2005-05-03 16:49:25 IP:211.22.xxx.xxx 未訂閱
SamSam1230,我認為你應該要適時的觸發THREAD及停止THREAD才是,不然THREAD一起動就沒有停止過HANG在那個WHILE TRUE的迴圈裡,程式一開始CREATE THREAD為FALSE,才依照你程式理的需求適時的RESUME及SUSPEND THREAD才是吧! ----------------------------------------------- Creation is the fundation of promotion.
SamSam1230
中階會員


發表:128
回覆:178
積分:65
註冊:2004-12-23

發送簡訊給我
#6 引用回覆 回覆 發表時間:2005-05-03 17:05:37 IP:218.103.xxx.xxx 未訂閱
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

發送簡訊給我
#7 引用回覆 回覆 發表時間:2005-05-03 18:31:07 IP:60.248.xxx.xxx 未訂閱
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

發送簡訊給我
#8 引用回覆 回覆 發表時間:2005-05-04 10:16:44 IP:218.103.xxx.xxx 未訂閱
大大呀還是一樣呀.............. threading 一直printout mainform就當掉一樣 動不了
hagar
版主


發表:143
回覆:4056
積分:4445
註冊:2002-04-14

發送簡訊給我
#9 引用回覆 回覆 發表時間:2005-05-04 10:28:45 IP:202.39.xxx.xxx 未訂閱
插個花, 小弟不熟 thread 小弟以為一直做 Memo.Lines.Add 這個動作本來就很吃 Loading 不知道您為什麼要在 thread 裡做這個動作? 沒什麼特別的話, 應該用個 TTimer 就可以達成這個目的 沒必要用到 thread -- hagar.
SamSam1230
中階會員


發表:128
回覆:178
積分:65
註冊:2004-12-23

發送簡訊給我
#10 引用回覆 回覆 發表時間:2005-05-04 11:00:07 IP:218.103.xxx.xxx 未訂閱
回應 hager 大大 我只是用memo來看看要怎樣做thread才確定不會影響到foreground 的 mainform 的運作 我的最終要做的不是要printout message 到memo 啦 因為我有一大堆的Database 的東西要一直動 所以用timer 會令到foreground 的 mainform 好像當掉了一樣 當初我寫了thread 但出來的效果一樣mainform 會像當掉了一樣 所以就有個想法用memo 來看看是不是我寫那裡錯了 但發現我只是printout 一句的message 也會這樣
jest0024
高階會員


發表:11
回覆:310
積分:224
註冊:2002-11-24

發送簡訊給我
#11 引用回覆 回覆 發表時間:2005-05-04 11:30:21 IP:211.74.xxx.xxx 未訂閱
引言:
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

發送簡訊給我
#12 引用回覆 回覆 發表時間:2005-05-04 11:55:16 IP:218.103.xxx.xxx 未訂閱
jest0024 大大 可以再詳細告訴我嗎? 我真的不太懂thread 這也是我第一次寫thread 謝謝
jest0024
高階會員


發表:11
回覆:310
積分:224
註冊:2002-11-24

發送簡訊給我
#13 引用回覆 回覆 發表時間:2005-05-04 15:48:48 IP:61.60.xxx.xxx 未訂閱
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

發送簡訊給我
#14 引用回覆 回覆 發表時間:2005-05-04 17:37:15 IP:218.103.xxx.xxx 未訂閱
jest0024 大大你的方法 yyu10大大已經提供過 我也try 過, 但都不行.
jest0024
高階會員


發表:11
回覆:310
積分:224
註冊:2002-11-24

發送簡訊給我
#15 引用回覆 回覆 發表時間:2005-05-04 19:04:38 IP:211.74.xxx.xxx 未訂閱
引言: 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

發送簡訊給我
#16 引用回覆 回覆 發表時間:2005-05-05 05:34:21 IP:220.245.xxx.xxx 未訂閱
仅仅是一个猜测.    你是不是在主绪(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

發送簡訊給我
#17 引用回覆 回覆 發表時間:2005-05-05 09:59:27 IP:218.103.xxx.xxx 未訂閱
引言: 仅仅是一个猜测. 你是不是在主绪(Form1)中直接呼叫了Execute? 如果是, 将该行代码去掉试试.
   athread := DBThread.Create;  //保留
   athread.Execute;             //去掉
_________________________ Programming is a passion
是呀
    DBThread := DBHandler.Create(button1click); 
DBThread.Execute();     
不是這樣用的嗎??? 哎呀... 那把DBThread.Execute(); 拿掉 真的拿掉就好了 但實在不明白, 請問有大大可以講解一下嗎? execute 那要來做什麼? 是不是create 之後就會自動的執行?
系統時間:2024-05-17 12:41:20
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!