WaitForSingleObject问题

时间:2011-07-06 17:40:25

标签: c++ windows multithreading winapi synchronization

首先仔细阅读问题。

有一个工作线程从CTest类的CreateInstance中生成。这是班级的原型。 hThread是线程的句柄,hEventShutdown是用于在程序退出时关闭线程的事件。 WaitForShutdown是一个公共函数,用于发出信号hEventShutdown并等待句柄线程,直到线程正常退出。从应用程序的退出调用WaitForShutdown。

//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的指针。这意味着调用CTest的析构函数,这显然会关闭线程句柄(hThread)。但WaitForShutdown中的WaitForSingleObject实际上正在等待线程句柄。所以这里的行为将是不确定的(我想是的,如果我错了,你可以纠正我)。另一个问题是当WaitForSingleObject在其成员hThread上等待不正确时,调用Ctest的析构函数。我无法从线程中删除删除pTest,因为由于某些原因它必须在那里。

您如何建议上述解决方案?

我能想到的几个解决方案:

  1. 我可以在另一张地图中保留线程句柄,但我不想这样做。
  2. 我可以在WaitForShutdown中的WaitForSingleObject之前将线程句柄复制到某个局部变量,并将等待它。不知道是不是?你告诉我。
  3. 或者我将使用Duplicatehandle API在WaitForSingleObject之前获取现有线程句柄的引用并等待它。不知道是不是正确的。不知道在原始的CloseHandle之后,重复的句柄是否会存活。
  4. 我将保留线程ID,从线程ID获取线程句柄并在WaitForShutdown中继续等待线程句柄。这看起来更优雅,但我不知道有没有办法从线程ID获取句柄。
  5. 纠正我。

    您的反馈表示赞赏。

2 个答案:

答案 0 :(得分:2)

处理此问题的最简单方法是在WaitForSingleObject返回后从WaitForShutdown中删除线程。这确保了您需要的所有句柄 - 更重要的是,对象本身 - 保持活力到最后。

答案 1 :(得分:1)

我按原样运行了这件作品。似乎它有效,并且它不会崩溃。 奇怪的是,在我们离开CloseHandle(hthread)之前,我们可以致电WaitforSingleObject(hThread,INFINITE)。 当然,加入线程的“学术”方式首先是WaitForSingleObject(hThread,INFINITE)而不是CloseHandle(hThread)。这就是我的建议 - 以这种方式做。

我不必再添加了。