2011-07-06 6 views
1

まず、問題を注意深くお読みください。WaitForSingleObjectの問題

CTestクラスのCreateInstanceから生成されたワーカースレッドがあります。ここにクラスのプロトタイプがあります。 hThreadはスレッドへのハンドルで、hEventShutdownはプログラム終了時にスレッドをシャットダウンするために使用されるイベントです。 WaitForShutdownは、hEventShutdownを通知し、スレッドが正常に終了するまでスレッドのハンドルを待機するために使用されるパブリック関数です。 WaitForShutdownは、アプリケーションのExitから呼び出されます。

//pseudocode 
CTest 
{ 
public: 
CTest* CreateInstance(); 
static threadproc(void *pv); 
void WaitForShutdown(); 

public: 
HANDLE hThread; 
HANDLE hEventShutdown; 

} 

void CTest::CTest* CreateInstance() 
{ 
    // spawn a thread, pass 'this' pointer to thread , use beginthreadex 

    hThread = beginthreadex (threadproc, this); 
} 


unsigned int CTest::threadproc(void *pv) 
{ 

    Ctest *ptest = (Ctest*)pv; 

    do 
    { 
     HANDLES hArray[2] = { pv->hEventShutdown, someotherhandle } 

     dwResult = Waitformultipleobjects(hArrary , 2); 

    if (dwResult == WAIT_OBJECT_0) 
     delete pTest; // since it is allocated dynamically (This is required due to some known reasons in my code) 

    if(dwResult == WAIT_OBJECT_0 + 1) 
     Doprocessing(); //DoProcessing when other thread signal someotherhandle 

    }while (1) 

void CTest::WaitForShutdown() 
{ 
    SetEvent (hEventShutdown); 

    WaitForSingleObject (hThread,INFINITE); 

} 

void CTest::~CTest() 
{ 
    Closehandle(hThread) 
    Closehandle(hEventShutdown); 
} 

は今、あなたは慎重にコードを見れば、あなたはそのイベントがWaitForShutdown関数から通知されるでしょう、スレッドはWaitForMultipleOjbectsから出てくるとCTESTのポインタを削除します。これは、明らかにスレッドハンドル(hThread)を閉じるCTestのデストラクタが呼び出されたことを意味します。 WaitForShutdownのWaitForSingleObjectは、実際にはスレッドハンドルで待機しています。だからここでの動作は未定義です(私はそうだと思いますが、私が間違っていれば修正することができます)。別の問題は、WaitForSingleObjectがメンバーhThreadを待っているときにCtestのデストラクタが正しく呼び出されなかったことです。何らかの理由でそこに存在しなければならないので、私はスレッドからdelete pTestを削除できません。

上記の解決策をどのように提案しますか?私は考えることができるソリューションの

カップル:

  1. 私は別のマップにスレッドハンドルを保つことができますが、私はそれをしたいいけません。
  2. WaitForShutdownのWaitForSingleObjectの前にスレッドハンドルをいくつかのローカル変数にコピーしておきます。ドン;それは正しいのですか?教えてください。
  3. または、Duplicatehandle APIを使用して、WaitForSingleObjectの前に既存のスレッドハンドルの参照を取得し、待機します。正しいのは分かりません。オリジナルのCloseHandleの後に複製ハンドルが生きているかどうかは分かりません。
  4. スレッドIDを保持し、スレッドIDからスレッドハンドルを取得し、WaitForShutdownのスレッドハンドルを待機します。これはよりエレガントに見えますが、スレッドIDからハンドルを取得する方法はありません。

私を訂正します。

お客様の声援に感謝します。

答えて

2

これを処理する最も簡単な方法は、WaitForSingleObjectが返された後、単にWaitForShutdownからスレッドを削除することです。これにより、必要なすべてのハンドル(より重要なことには、オブジェクト自体)が確実に終了します。

1

これをそのまま実行しました。それが動作しているように見えますが、クラッシュしません。 WaitforSingleObject(hThread,INFINITE)の外に出る前に、私たちはCloseHandle(hthread)と呼ぶことができるというのは不思議です。 もちろん、スレッドに参加する「学術的な」方法は、WaitForSingleObject(hThread,INFINITE)よりも先にCloseHandle(hThread)です。それが私の提案です - このようにしてください。

私はもはや追加する必要はありません。

+0

"学術"以上のものが正しい。ハンドルが閉じられた後、それはもはや有効ではありません。 –

関連する問題