等待Thread結束 |
答題得分者是:aftcast
|
raistlinmiao
一般會員 發表:17 回覆:20 積分:12 註冊:2004-10-22 發送簡訊給我 |
請問一下各位
我有一個函式,其中會啟動一個Thread,希望能等待Thread Suspend後再繼續下去 但使用WaitForInputIdle及 waitforsingleobject都不能做到 請問各位高手,要如何解決,謝謝 以下是函式 { TurnWaiting->Resume(); WaitForInputIdle((HANDLE)TurnWaiting->Handle, INFINITE); //do something after TurnWaiting Suspend.... } | |
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
1需要自己先createevent,參考如下
mDoWorkFlag = ::CreateEvent( NULL, // default security attributes TRUE, // manual-reset event TRUE, // initial state is signaled "NotifyWork" // object name ); 上面的mDoWorkFlag必需是全域的變數 2/在你呼叫TurnWaiting->Suspend( )的下面加上一條 ::SetEvent(mDoWorkFlag); 3/ 使用waitforsingleobj(mDoWorkFlag,INFINITE) 4/ 在做好所有的事後加::ResetEvent(mDoWorkFlag); 寫到這裡,我突然看到你的程式碼怎怪怪的???!! { TurnWaiting->Resume(); //resume後你怎麼會期待它自己suspend?? 等它terminate還有可能! 或者你在等使用者自己去按某個鍵然後suspend? WaitForInputIdle((HANDLE)TurnWaiting->Handle, INFINITE); //do something after TurnWaiting Suspend.... } 我已經告訴你方法了,可是你的程式logical有些問題,自己要想清楚。 或者你把程式的流程講一下… 我實在是想不到這樣的應用方式… 疑?? 剛又看了一下你的標題,怎麼會是「等thread結束」,到底是suspend還是結束?? 若是結束,那問題非常的簡單,只要用TurnWaiting->WaitFor就搞定了
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan
編輯記錄
aftcast 重新編輯於 2008-11-27 09:53:16, 註解 無‧
|
|
raistlinmiao
一般會員 發表:17 回覆:20 積分:12 註冊:2004-10-22 發送簡訊給我 |
我這個程式碼是一個函式,執行到某個條件的時候 需要等待使用者從form上面的button或是其它vcl做出操作 然後根據操作的內容然後運算後回傳一個值 有點類似象棋AI程式,玩家在上面移動棋子以後,電腦再做出相對應的應手 但是玩家在下決定之前,電腦也在背景思考 目前的想法是按下button的時候 把參數傳給TThread 然後順便呼叫Suspend 函式就可以繼續 不過遇到的問題就是 thread在執行的時候 函式會直接跳過他回傳一個值 造成錯誤 因為不是正確的結果 使用waitfor的話我也想過 不過會發生整個Form被凍結 然後無法讓使用者操作button的情況 再次感謝您的熱心回應 我晚點來試試這個方法 ===================引 用 aftcast 文 章=================== 1需要自己先createevent,參考如下 mDoWorkFlag = ::CreateEvent( NULL, // default security attributes TRUE, // manual-reset event TRUE, // initial state is signaled "NotifyWork" // object name ); 上面的mDoWorkFlag必需是全域的變數 2/在你呼叫TurnWaiting->Suspend( )的下面加上一條 ::SetEvent(mDoWorkFlag); 3/ 使用waitforsingleobj(mDoWorkFlag,INFINITE) 4/ 在做好所有的事後加::ResetEvent(mDoWorkFlag); 寫到這裡,我突然看到你的程式碼怎怪怪的???!! { TurnWaiting->Resume(); //resume後你怎麼會期待它自己suspend?? 等它terminate還有可能! 或者你在等使用者自己去按某個鍵然後suspend? WaitForInputIdle((HANDLE)TurnWaiting->Handle, INFINITE); //do something after TurnWaiting Suspend.... } 我已經告訴你方法了,可是你的程式logical有些問題,自己要想清楚。 或者你把程式的流程講一下… 我實在是想不到這樣的應用方式… 疑?? 剛又看了一下你的標題,怎麼會是「等thread結束」,到底是suspend還是結束?? 若是結束,那問題非常的簡單,只要用TurnWaiting->WaitFor就搞定了 |
|
raistlinmiao
一般會員 發表:17 回覆:20 積分:12 註冊:2004-10-22 發送簡訊給我 |
您好:
剛剛試了您的方法 因為這是第一次寫thread程式 不知道有沒有誤用 但是還是沒有達成預期的效果 我寫了一個比較簡單的測試程式 能否請幫我看看 謝謝 以下是Button3按下以後,程式會開始等待看是Button1被按了,還是Button2 Thread的h //--------------------------------------------------------------------------- #ifndef Unit2H #define Unit2H //--------------------------------------------------------------------------- #include //--------------------------------------------------------------------------- class testThread : public TThread { private: protected: void __fastcall Execute(); public: __fastcall testThread(bool CreateSuspended); int Pressed; }; //--------------------------------------------------------------------------- #endif Thread的cpp //--------------------------------------------------------------------------- #include #pragma hdrstop #include "Unit2.h" #pragma package(smart_init) //--------------------------------------------------------------------------- // Important: Methods and properties of objects in VCL can only be // used in a method called using Synchronize, for example: // // Synchronize(UpdateCaption); // // where UpdateCaption could look like: // // void __fastcall testThread::UpdateCaption() // { // Form1->Caption = "Updated in a thread"; // } //--------------------------------------------------------------------------- __fastcall testThread::testThread(bool CreateSuspended) : TThread(CreateSuspended) { Pressed = 0; } //--------------------------------------------------------------------------- void __fastcall testThread::Execute() { //---- Place thread code here ---- while(Pressed == 0) { Sleep(1000); //等待到pressed變數改變 } } //--------------------------------------------------------------------------- Form的h //--------------------------------------------------------------------------- #ifndef Unit1H #define Unit1H //--------------------------------------------------------------------------- #include #include #include #include <Forms.hpp><br />#include "Unit2.h" //--------------------------------------------------------------------------- class TForm1 : public TForm { __published: // IDE-managed Components TButton *Button1; TButton *Button2; TButton *Button3; void __fastcall FormCreate(TObject *Sender); void __fastcall Button3Click(TObject *Sender); void __fastcall Button1Click(TObject *Sender); void __fastcall Button2Click(TObject *Sender); private: // User declarations public: // User declarations __fastcall TForm1(TComponent* Owner); testThread* test; HANDLE mDoWorkFlag; }; //--------------------------------------------------------------------------- extern PACKAGE TForm1 *Form1; //--------------------------------------------------------------------------- #endif Form的cpp //--------------------------------------------------------------------------- #include #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { test = new testThread(true); mDoWorkFlag = ::CreateEvent( NULL, // default security attributes TRUE, // manual-reset event TRUE, // initial state is signaled "NotifyWork" // object name ); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button3Click(TObject *Sender) { test->Resume(); //按下後程式進入等待 直到test被suspend ::SetEvent(mDoWorkFlag); WaitForSingleObject(mDoWorkFlag,INFINITE); ::ResetEvent(mDoWorkFlag); if (test->Pressed == 1) //suspend後,開始判斷 { ShowMessage("Button1"); } else if (test->Pressed ==2) { ShowMessage("Button2"); } ShowMessage("out"); //失敗了,因為沒有等thread結束後才往下走 } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { test->Pressed = 1; //按下以後 更改thread裡的變數 然後suspend test->Suspend(); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { test->Pressed = 2; test->Suspend(); } //--------------------------------------------------------------------------- |
|
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
===================引 用 raistlinmiao 文 章=================== 您好: 剛剛試了您的方法 因為這是第一次寫thread程式 不知道有沒有誤用 但是還是沒有達成預期的效果 我寫了一個比較簡單的測試程式 能否請幫我看看 謝謝 以下是Button3按下以後,程式會開始等待看是Button1被按了,還是Button2 Thread的h //--------------------------------------------------------------------------- #ifndef Unit2H #define Unit2H //--------------------------------------------------------------------------- #include //--------------------------------------------------------------------------- class testThread : public TThread { private: protected: void __fastcall Execute(); public: __fastcall testThread(bool CreateSuspended); int Pressed; }; //--------------------------------------------------------------------------- #endif Thread的cpp //--------------------------------------------------------------------------- #include #pragma hdrstop #include "Unit2.h" #pragma package(smart_init) //--------------------------------------------------------------------------- // Important: Methods and properties of objects in VCL can only be // used in a method called using Synchronize, for example: // // Synchronize(UpdateCaption); // // where UpdateCaption could look like: // // void __fastcall testThread::UpdateCaption() // { // Form1->Caption = "Updated in a thread"; // } //--------------------------------------------------------------------------- __fastcall testThread::testThread(bool CreateSuspended) : TThread(CreateSuspended) { Pressed = 0; } //--------------------------------------------------------------------------- void __fastcall testThread::Execute() { //---- Place thread code here ---- while(Pressed == 0) { Sleep(1000); //等待到pressed變數改變 } } //--------------------------------------------------------------------------- Form的h //--------------------------------------------------------------------------- #ifndef Unit1H #define Unit1H //--------------------------------------------------------------------------- #include #include #include #include <forms.hpp><br />#include "Unit2.h" //--------------------------------------------------------------------------- class TForm1 : public TForm { __published: // IDE-managed Components TButton *Button1; TButton *Button2; TButton *Button3; void __fastcall FormCreate(TObject *Sender); void __fastcall Button3Click(TObject *Sender); void __fastcall Button1Click(TObject *Sender); void __fastcall Button2Click(TObject *Sender); private: // User declarations public: // User declarations __fastcall TForm1(TComponent* Owner); testThread* test; HANDLE mDoWorkFlag; }; //--------------------------------------------------------------------------- extern PACKAGE TForm1 *Form1; //--------------------------------------------------------------------------- #endif Form的cpp //---------------------------------------------------------------------------</forms.hpp></stdctrls.hpp> #include #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { test = new testThread(true); mDoWorkFlag = ::CreateEvent( NULL, // default security attributes TRUE, // manual-reset event FALSE, // initial state is signaled //這裡改成一開始是無訊號的,即阻檔的 "NotifyWork" // object name ); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button3Click(TObject *Sender) { test->Resume(); //按下後程式進入等待 直到test被suspend WaitForSingleObject(mDoWorkFlag,INFINITE); //這裡開始一直等待直到mDoWorkFlag被通知放行 ::ResetEvent(mDoWorkFlag); //這裡的意思是把事件物件又設定為阻檔的 if (test->Pressed == 1) //suspend後,開始判斷 { ShowMessage("Button1"); } else if (test->Pressed ==2) { ShowMessage("Button2"); } ShowMessage("out"); //失敗了,因為沒有等thread結束後才往下走 Button1->Enabled = true; //此行與下行是我精心幫你設想的,為了防止多按幾次suspend, Button2->Enabled = true; //因為多按一次,resume要多執行一次才會起來,這是非常細的細節 } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { test->Pressed = 1; //按下以後 更改thread裡的變數 然後suspend Button1->Enabled = false; //此行與下行是我精心幫你設想的,為了防止多按幾次suspend, Button2->Enabled = false; //因為多按一次,resume要多執行一次才會起來,這是非常細的細節 test->Suspend(); ::SetEvent(mDoWorkFlag); //將事件物件設定為有訊號的,即可通行的 } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { test->Pressed = 2; Button1->Enabled = false; //此行與下行是我精心幫你設想的,為了防止多按幾次suspend, Button2->Enabled = false; //因為多按一次,resume要多執行一次才會起來,這是非常細的細節 test->Suspend(); ::SetEvent(mDoWorkFlag); //將事件物件設定為有訊號的,即可通行的 } //---------------------------------------------------------------------------
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
|
raistlinmiao
一般會員 發表:17 回覆:20 積分:12 註冊:2004-10-22 發送簡訊給我 |
||
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
嗯,我跟著你的想法去改竟忘了會有凍結的情形!!
晚點有時間再幫你想看看。 此外,初步的概念是你可能需再建立一個thread,然後把waitforsingleobject放在新thead上。事實上這個api通常是用在thead上的面的。 你可以提供一下你原來的thead裡面是要做什麼嗎? 你只寫了sleep,我想知道你大概是想做什麼… 整個程式的logical還是有點怪怪的,當然,也許是我不了解你真的用意是什麼,你只說了大概像是象棋ai的情形…
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
|
raistlinmiao
一般會員 發表:17 回覆:20 積分:12 註冊:2004-10-22 發送簡訊給我 |
感謝您的回應
我想寫的是一個遊戲 類似象棋 電腦動一步以後 玩家再動一步 但是玩家在思考的時候 電腦也在思考 電腦動作以後會開啟一個函式 函式執行到一半 會需要玩家去移動Form上面的vcl元件 然後再根據元件的移動來產生結果 所以那函式裡面就是Sleep();來等待玩家 邏輯可能是真的怪怪的.. 如果真的不行的話 目前的權宜想法 就是先條件產生時 先開啟一個函式叫醒thread 然後函式結束 等到thread執行完了 再透過sendmessage給form 然後form再去呼叫另一函式來計算結果 不過這樣寫的話 整個結構會變的怪怪的 再次感謝您熱心的指導 ===================引 用 aftcast 文 章=================== 嗯,我跟著你的想法去改竟忘了會有凍結的情形!! 晚點有時間再幫你想看看。 此外,初步的概念是你可能需再建立一個thread,然後把waitforsingleobject放在新thead上。事實上這個api通常是用在thead上的面的。 你可以提供一下你原來的thead裡面是要做什麼嗎? 你只寫了sleep,我想知道你大概是想做什麼… 整個程式的logical還是有點怪怪的,當然,也許是我不了解你真的用意是什麼,你只說了大概像是象棋ai的情形… |
|
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
早,昨晚竟失眠,就因為想不出你這個問題的內容流程是如何的。
了解你說明了二次類似象棋的game,但詳細一點的流程圖都沒有,比如說1按button2做什麼3再如何4…… 又,你說: 電腦動作以後會開啟一個函式 函式執行到一半 會需要玩家去移動Form上面的vcl元件 然後再根據元件的移動來產生結果 所以那函式裡面就是Sleep();來等待玩家 不清楚這段話是什麼意思。是開一個怎樣的函式?大概是做啥功能? 而最後一句話,裡面就是SLEEP ? 難道你那個thread裡真的就只需要執行一句話sleep?就一句? 想了很久,我自己就當你是寫象棋來看待,但發現你的寫法和象棋好像差很多。比如說 為何會需要suspend??? 這個問題是我試著回你的時候發現的,好像沒有很好的理由需要suspend一個thread後才能去做什麼事! 我本來想好要設定二個thread的結構來處理你的問題,但發現套不上你的想法… 下面是我一早試著寫給你的東西 1/ 產生一個thread_brain,它負責背景不停的"思考",它接受來自user透過元件傳來的一些參數,並進一步的變化"思路" 2/ 產生另一個thread_worker,它主要用來負責user操作元件後的後序處理,比如說更動某些元件的屬性,把一些訊息傳給thead_brain。 流程與限制: 1/ 開始的時候thread_brain就啟動,直到user按下某些元件後被suspend 2/ 開始的時候thread_worker是不啟動的,直到user按下某元件後再把它啟動 3/ 當user按下元件後…… 寫到3的時候,我發現自己寫不下去,因為好像都不需要suspned之類的,且好像一個thread也可以解決你的問題 我很頭痛,我很想幫你,但似乎在沒理清你的結構時是幫不了的。可能的話請試著像我上面那樣分析流程,並寫出來。每個thead的功能,每個函式的功能,整個動作的流程方向等… 而大概的說法就不用了,我懂你大概是要寫類似象棋的東西… 注: suspend與waitforsingleobject 有一點點類似,但決決大多數不會使用suspend。若你要確定某種情形下才開始做下面的動作,那100%是用waitforsingleobjcet。這二個似乎不可能混在一起用,更進一步的說,suspend應該不需要存在而可以用waitforsingleobjcet來取代一切!! 所以我真的該了解你為何一定要suspned?? 也許你想要的不是你該用的函式。
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan
編輯記錄
aftcast 重新編輯於 2008-11-28 10:21:18, 註解 無‧
|
|
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
寫完上一篇的一推話後,我有一點的想法,先幫你改成一個較正式的範例,是照我自己的想法做的。
但還是請你回覆我上篇的內容喔! Thread的h //--------------------------------------------------------------------------- #ifndef Unit2H #define Unit2H //--------------------------------------------------------------------------- #include //--------------------------------------------------------------------------- class testThread : public TThread { private: protected: void __fastcall Execute(); public: __fastcall testThread(bool CreateSuspended); int Pressed; Form1->Button1->Enabled = true; //此行與下行是我精心幫你設想的,為了防止多按幾次suspend, Form1->Button2->Enabled = true; //因為多按一次,resume要多執行一次才會起來,這是非常細的細節 while (!Terminated) //不停的處理事情 for (int 1= 1; i <100; i ) ; //這句話是模擬你可能要事前處理的事務 if ( WaitForSingleObject(Form1->mDoWorkFlag,INFINITE)==0L) //若有通知訊息才會放行下面的程式,不然就等在這裡 if (pressed = 2) ::MessageBox(0,"Botton2 pressed","",MB_OK); ::ResetEvent(Form1->mDoWorkFlag); Synchronize(UpdateButton); //把form的button 再show 出來 void __fastcall TForm1::Button3Click(TObject *Sender) test->Resume(); //這裡執行後會造成thread裡的一段程式開跑,哪一段? waitforsingleobject前的那一些前戲 void __fastcall TForm1::Button1Click(TObject *Sender) test->Pressed = 1; //按下以後 更改thread裡的變數 然後suspend 此時thead的wait那段就會自動開跑了… } void __fastcall TForm1::Button2Click(TObject *Sender) test->Pressed = 2; 此時thead的wait那段就會自動開跑了… } //--------------------------------------------------------------------------- 我沒實際在bcb上跑,我是用我的腦子跑著改的,故可能會有語法或是錯別字,compile有誤時請自行修改。但架構就是這樣!
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
|
raistlinmiao
一般會員 發表:17 回覆:20 積分:12 註冊:2004-10-22 發送簡訊給我 |
您好:
感謝您這麼費心在我的問題上面 原本以為整個程式的架構是不用寫出來來讓問題變更複雜 不過經過您這麼一說 我發現有可能是我的邏輯上的問題 讓整個流程陷入了死路 我說一下我整個程式想做的東西請您參考一下 其實就是類似象棋的棋類小遊戲 但是要分成可以人類跟人類玩 人類跟ai玩 還有ai跟ai 而且隨時可以換手(電腦接手人類這邊 或人類接手電腦) 目前的做法是先在Form下面宣告一個Game class 然後Game class下面有兩個player class 然後ai及human class繼承player class 所以當換手的時候我就把指標換人 遊戲可以繼續進行 目前game class的簡化流程是 currentgame = player1->nextmove(); currentgame = player2->nextmove(); ... 想完然後回傳 問題是不論是人類或是電腦在思考的時候 不會馬上回傳答案 所以必需等待 也就是sleep(); 現在的做法就是換人類的時候 先sleep(); 等待盤面被移動的時候 把盤面轉換成參數 然後傳給player 然後player再回傳給game 但是一sleep整個畫面是被凍結的 所以人類不能移動盤面 所以想開個thread 接下來就有上面的問題 不過現在來看 好像就是這個想法讓整個流程有誤 如果只是簡單的下棋程式 那一般的做法是為何呢? 真的非常感謝您這麼熱心 <(_ _)> |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |