Q: How to check if a thread is still active?

A: One often used method is to call GetExitCodeThread function, then see if returns STILL_ACTIVE value.

Example
Code:
DWORD CheckIfThreadIsStillActive(DWORD dwThreadID, BOOL& bIsActive)
{
   bIsActive = FALSE;
   HANDLE hThread = ::OpenThread(THREAD_QUERY_INFORMATION, FALSE, dwThreadID);
   if(NULL == hThread)
      return ::GetLastError();
   
   DWORD dwExitCode = 0;
   BOOL bRet = ::GetExitCodeThread(hThread, &dwExitCode);
   ::CloseHandle(hThread);
   if(! bRet)
      return ::GetLastError();

   if(STILL_ACTIVE == dwExitCode)
      bIsActive = TRUE;
   
   return NO_ERROR;
}
This method is generally OK but has a little disadvantage: it is possible that thread has been terminated returning exactly the STILL_ACTIVE value.
That may lead in troubles because of the false assumption.

Other more reliable way is to call WaitForSingleObject function, passing 0 (zero) value for time-out parameter.
In this case, WaitForSingleObject does not enter in wait state and returns immediately.
If the returned value is WAIT_TIMEOUT, then the thread is still active.

Example
Code:
DWORD CheckIfThreadIsStillActive(DWORD dwThreadID, BOOL& bIsActive)
{
   bIsActive = FALSE;
   HANDLE hThread = ::OpenThread(SYNCHRONIZE, FALSE, dwThreadID);
   if(NULL == hThread)
      return ::GetLastError();

   DWORD dwRet = ::WaitForSingleObject(hThread, 0);
   ::CloseHandle(hThread);
   if(WAIT_FAILED == dwRet)
      return ::GetLastError();

   if(WAIT_TIMEOUT == dwRet)
      bIsActive = TRUE;

   return NO_ERROR;
}
Notes
  • For GetExitCodeThread, the thread handle must have THREAD_QUERY_INFORMATION access right;
  • For WaitForSingleObject, the thread handle must have SYNCHRONIZE access right.


Resources