WaitForSingleObject problem

WaitForSingleObject problem

本文关键字:problem WaitForSingleObject      更新时间:2023-10-16

先仔细阅读问题。

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

你将如何建议解决上述问题?

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

  1. 我可以保持线程句柄在另一个地图,但我不想这样做。
  2. 我可以复制线程句柄到一些本地变量之前WaitForSingleObject在WaitForShutdown,并将等待它。不知道这样对不对?你告诉我。
  3. 或者我将使用Duplicatehandle API在WaitForSingleObject之前获得现有线程句柄的引用并等待它。不知道这是否正确。不知道复制句柄是否会在原始句柄的CloseHandle之后存活。我将保留线程ID,从线程ID获取线程句柄,并在WaitForShutdown中等待线程句柄。这看起来更优雅,但我不知道是否有任何方法从线程id获得句柄。

纠正我。

感谢您的反馈。

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

我已经按原样运行了这篇文章。看起来很好用,而且不会崩溃。奇怪的是,我们可以调用CloseHandle(hthread),在我们离开WaitforSingleObject(hThread,INFINITE)之前。当然,"学术"的方式连接线程首先是WaitForSingleObject(hThread,INFINITE)而不是CloseHandle(hThread)。这就是我的建议——这样做。

不用再加了