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

TThread 問題

答題得分者是:microbean
kenbcb
中階會員


發表:171
回覆:129
積分:60
註冊:2003-07-15

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-02-04 17:22:50 IP:220.130.xxx.xxx 未訂閱
請問各位,    以下程式,是我試著用thread 來做,但結果用windows工作管理員看到當按下button時, 會執行thread起來,當thread執行一次之後就結束了(我沒關掉thread), thread不是一直執行嗎?  並且thread執行起來,就無法移動form了    請各位大大指導!  
     //啟動thread的地方
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   Memo1->Clear();       //create read rs232 thread
   readRS232 = new TReadRS232(false);
}
//---------------------------------------------------------------------------    //thread程式
#include 
#pragma hdrstop    #include "Unit1.h"
#include "Unit2.h"
#pragma package(smart_init)
extern HANDLE hComm;
//---------------------------------------------------------------------------
__fastcall TReadRS232::TReadRS232(bool CreateSuspended)
        : TThread(CreateSuspended)
{
   FreeOnTerminate = true;
}
//---------------------------------------------------------------------------
void __fastcall TReadRS232::Execute()
{
   //---- Place thread code here ----
   Synchronize(Read232);
}
//---------------------------------------------------------------------------
void __fastcall TReadRS232::Read232()
{
   //COM Port event parse
   if(hComm == INVALID_HANDLE_VALUE) return;       TEvent *WEvent;
   OVERLAPPED OverLap;
   unsigned long EvWait,dwRece;       WEvent = new TEvent(NULL,true,false,"");  //create evnet object
   OverLap.hEvent = (HANDLE)WEvent->Handle;   //event handle assign 'Overlap'       //wait event occur
   WaitCommEvent(hComm,&EvWait,&OverLap);
   if(GetOverlappedResult(hComm,&OverLap,&dwRece,true))
   {
      //if(WEvent->WaitFor(10) != wrSignaled) return;  //if(event not occur) exit
      WEvent->ResetEvent();  //clear event          //a break was detected on input
      if(EvWait & EV_BREAK) Form1->Memo1->Lines->Add("Break Signal");          //the CTS(clear to send) signal changed state
      if(EvWait & EV_CTS) Form1->Memo1->Lines->Add("CTS");          //the DSR(data set ready) signal changed state
      if(EvWait & EV_DSR) Form1->Memo1->Lines->Add("DSR");          //a line status error occurred(inldue:CE_FRAME,CE_OVERRUN,CE_RXPARITY)
      if(EvWait & EV_ERR) Form1->Memo1->Lines->Add("Error");          //a RING indicator was detected
      if(EvWait & EV_RING) Form1->Memo1->Lines->Add("RING");          //the RLSD(receive line signal detect) signal changed state
      if(EvWait & EV_RLSD) Form1->Memo1->Lines->Add("RLSD");          //a character was received and placed in the input buffer
      if(EvWait & EV_RXCHAR) Form1->Memo1->Lines->Add("RXCHAR");          //check RXFLAG
      if(EvWait & EV_RXFLAG) Form1->Memo1->Lines->Add("RXFLAG");          //the last character in the output buffer was sent
      if(EvWait & EV_TXEMPTY) Form1->Memo1->Lines->Add("Send Buffer empty");
   }
   else
   {
      //show error message
      LPVOID lpMsgBuf;
      long Format = FORMAT_MESSAGE_ALLOCATE_BUFFER 
                    FORMAT_MESSAGE_FROM_SYSTEM 
                    FORMAT_MESSAGE_IGNORE_INSERTS;
      DWORD ErrorCode = GetLastError();
      WORD Language = MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT);
      FormatMessage(Format,NULL,ErrorCode,Language,(LPTSTR)&lpMsgBuf,0,NULL);          AnsiString MsgStr;
      MsgStr = AnsiString((char*)lpMsgBuf).Trim() "(" IntToStr(ErrorCode) ")";
      Form1->Memo1->Lines->Add(MsgStr);
   }
}
//---------------------------------------------------------------------------
發表人 - kenbcb 於 2005/02/04 17:26:50
smartboss
初階會員


發表:19
回覆:93
積分:42
註冊:2004-12-29

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-02-04 18:38:59 IP:211.76.xxx.xxx 未訂閱
引言: 請問各位, 以下程式,是我試著用thread 來做,但結果用windows工作管理員看到當按下button時, 會執行thread起來,當thread執行一次之後就結束了(我沒關掉thread), thread不是一直執行嗎? 並且thread執行起來,就無法移動form了
void __fastcall TReadRS232::Execute() { //---- Place thread code here ---- while(!Terminated) { Synchronize(Read232); Sleep(100); } } 然後再做一個button 在button 裡放入 void __fastcall TForm1::Button2Click(TObject *Sender) { readRS232->Suspend(); } 來終止它。 再來您提到 form 無法動了,是因為您將整個緒都包在Synchronize() 裡使用,當緒遇到Synchronize() 時它就將它當成主緒來跑,所以 您的 form 當然是被放著不動了。 以上都是書上抄的,跟一位叫 lu 兄的教的,小弟也不會,您試試看可不可以吧。 蝦程速,有了 K.TOP 尊好。
kenbcb
中階會員


發表:171
回覆:129
積分:60
註冊:2003-07-15

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-02-05 10:08:42 IP:220.130.xxx.xxx 未訂閱
while(!Terminated) { Synchronize(Read232); Sleep(100); } 為什麼要用while 來一直跑呢,,,thread 不是用叫停止才停嗎,,, 我試的結果是一直form 不能動..但thread中的執行很正常...但這樣做好像沒發揮到thread功能
smartboss
初階會員


發表:19
回覆:93
積分:42
註冊:2004-12-29

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-02-05 11:33:51 IP:211.76.xxx.xxx 未訂閱
引言: while(!Terminated) { Synchronize(Read232); Sleep(100); } 為什麼要用while 來一直跑呢,,,thread 不是用叫停止才停嗎,,, 我試的結果是一直form 不能動..但thread中的執行很正常...但這樣做好像沒發揮到thread功能
thread 就像您說的「thread 不是用叫停止才停」,它是叫一次動一次的,所以才要您多設一個 button 去停掉它。 至於為何您的 form 一直不能動,上面己經有跟您說明過了,是因為您用了Synchronize() 之後它就將整段 thread 的部份當成是主程式在跑,所以您控製form 移動的那部份程式並不在 thread 裡,因此您怎麼動當然 form 他都不會動,除非您不要用Synchronize(),或者在遇到有使用 vcl 物件時才套用 Synchronize(),您thread 裡的WaitCommEvent(hComm,&EvWait,&OverLap);恐怕才是讓整個程是 hold 在那裡動也不動的主因,可能會有人叫您把Application->ProcessMessages(); 這一行插在您的 thread 裡,沒錯這樣您的form 就一定能動,且加越多行動的就越自在,但這是有遞迴風險的行為。 以上都是書上抄的,跟一位叫 lu 兄的教的,小弟也不會,您試試看可不可以吧。 蝦程速,有了 K.TOP 尊好。 發表人 - smartboss 於 2005/02/05 11:41:34
kenbcb
中階會員


發表:171
回覆:129
積分:60
註冊:2003-07-15

發送簡訊給我
#5 引用回覆 回覆 發表時間:2005-02-05 12:35:48 IP:61.222.xxx.xxx 未訂閱
在請問, 可否告訴 FreeOnTerminate /Synchronize() /WaitFor 是做什麼用的,不太了解help上的說明? 謝謝指導 發表人 - kenbcb 於 2005/02/05 14:18:52
microbean
初階會員


發表:1
回覆:43
積分:38
註冊:2004-04-09

發送簡訊給我
#6 引用回覆 回覆 發表時間:2005-02-05 15:01:23 IP:210.58.xxx.xxx 未訂閱
容許我 插花一下 我們可能都會誤解一件事,所謂的 執行緒 ,並不是一個獨立運作的程序(Process) , 執行緒可以與主要執行緒 (main thread) 同步工作, 但是他只是一個 function (or Procedure) , 所以我們可以想成, 建立了一個能獨立工作的 function , 或是 由系統呼叫了一個 獨立工作的 function , 所以既然是呼叫 function 都會需要有回傳 (return) . 所以當 Thread function 結束時, 就是代表 thread 結束了 . 所以用迴圈的意義是讓 thread function 先不 return . 而 suspend() , 是讓整個 thread function 停止往下執行 , 就很像按碼表暫停一樣 , 此時要用 resume 讓 thread 繼續走 , 並不是結束 thread. Synchronize() 的用意是讓 child thread 進入 main thread 中去執行. 舉個例子來解釋這個概念, 假設你的程序 (Process) 是敦化南路 , 敦化南路有快車道 與慢車道 , 假設快車道就是 main thread , 慢車道是 child thread,在正常的情形下 這兩個車道的車是不會發生碰撞的 , 並且互不影響 . Synchronize 的動作就像是 慢車道車輛要併入快車道一樣 , 慢車道要等快車道 沒有車了 , 才進入快車道 . 類似的情形 , 執行緒之所以要用 Synchronize , 是為了讓資源不會發生碰撞 , 也可以說是為了不讓 兩個執行緒同時存取同一個變數. 以你的例子來看, 要用 Synchronize 是因為你的 Main Thread 也就是 Main Form 上面 有可視元件 Memo1, 這些元件如果被 thread 同時存取 , 可能會發生問題 . VCL 把 thread 包裝成一個 class 叫作 TThread , 既然是一個 class 你呼叫了 create (new) , 就應該在不用的時候 , 呼叫 Free (delete). 但是因為 thread 的特性比較特殊, 有時 Main Thread 希望產生了 child Thread 後 就讓他"自生自滅" , VCL 設計了 FreeOnTerminate 就是為了當 Thread Function 結束 (Terminate)後, 可以自動呼叫 Free (delete) 這樣 MainThread 就可以不用管這個 class 的釋放問題了. _= 沒事就 winsock 一下 =_
smartboss
初階會員


發表:19
回覆:93
積分:42
註冊:2004-12-29

發送簡訊給我
#7 引用回覆 回覆 發表時間:2005-02-05 15:27:43 IP:211.76.xxx.xxx 未訂閱
引言: 在請問, 可否告訴 FreeOnTerminate /Synchronize() /WaitFor 是做什麼用的,不太了解help上的說明? 謝謝指導 發表人 - kenbcb 於 2005/02/05 14:18:52
FreeOnTerminate = true 就是代表它跑完了這一次的 thread 後會自己去把這個 thread 清掉 。 Synchronize() 就是防止您用 vcl 元件時造成 AccessViolation 的錯誤產生。 WaitFor 簡單的說就是令while(!Terminated) 這個的條件成立,好讓您在關掉thread 之前先去做一些事。 另外偶的那位lu 兄請我告訴您去買一本關於 thread 的書來看吧。 還有站上的資料也不少 這是 黃兄餐聚時的發表文章範例: http://delphi.ktop.com.tw/topic.php?topic_id=64439 而這是小弟我向lu兄跟 站上前輩討教的: http://delphi.ktop.com.tw/topic.php?TOPIC_ID=62520 發問前可以先去搜一下,這類的文章多到數不完,小弟董的只能算皮毛而己,祝您新年如意,寫 thread 順利。 蝦程速,有了 K.TOP 尊好。
系統時間:2024-05-02 22:17:46
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!