まず、問題を注意深くお読みください。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を削除できません。
上記の解決策をどのように提案しますか?私は考えることができるソリューションの
カップル:
- 私は別のマップにスレッドハンドルを保つことができますが、私はそれをしたいいけません。
- WaitForShutdownのWaitForSingleObjectの前にスレッドハンドルをいくつかのローカル変数にコピーしておきます。ドン;それは正しいのですか?教えてください。
- または、Duplicatehandle APIを使用して、WaitForSingleObjectの前に既存のスレッドハンドルの参照を取得し、待機します。正しいのは分かりません。オリジナルのCloseHandleの後に複製ハンドルが生きているかどうかは分かりません。
- スレッドIDを保持し、スレッドIDからスレッドハンドルを取得し、WaitForShutdownのスレッドハンドルを待機します。これはよりエレガントに見えますが、スレッドIDからハンドルを取得する方法はありません。
私を訂正します。
お客様の声援に感謝します。
"学術"以上のものが正しい。ハンドルが閉じられた後、それはもはや有効ではありません。 –