Как убить поток MFC?

Я создаю поток, используя AfxBeginThread, который представляет собой бесконечный цикл while:

UINT CMyClass::ThreadProc( LPVOID param )
{
  while (TRUE)
  {
      // do stuff
  }
  return 1;
}

Как убить этот поток в деструкторе класса?

Я думаю что-то вроде

UINT CMyClass::ThreadProc( LPVOID param )
{
  while (m_bKillThread)
  {
      // do stuff
  }
  return 1;
}

а затем установите m_bKillThread в FALSE в деструкторе. Но мне все еще нужно ждать в деструкторе, пока поток не будет мертв.

Ответ 1

Активно убивает поток:

Используйте возвращаемое значение AfxBeginThread (CWinThread*), чтобы получить дескриптор потока (m_hThread), затем передайте этот дескриптор API TerminateThread Win32. Это не безопасный способ прерывания потоков, поэтому, пожалуйста, прочитайте.

Ожидание завершения потока:

Используйте возвращаемое значение AfxBeginThread (CWinThread*), чтобы получить член m_hThread, затем используйте WaitForSingleObject(p->m_hThread, INFINITE); Если эта функция возвращает WAIT_OBJECT_0, то поток завершается. Вместо INFINITE вы также можете поставить количество миллисекунд, чтобы подождать, пока не произойдет тайм-аут. В этом случае возвращается WAIT_TIMEOUT.

Сигнал к вашему потоку, который должен завершиться:

Перед тем, как сделать WaitForSingleObject, просто установите какой-то флаг, который должен закрыть поток. Затем в основной петле потока вы должны проверить это значение bool и разбить бесконечный цикл. В вашем деструкторе вы должны установить этот флаг, затем выполните WaitForSingleObject.

Еще лучшие способы:

Если вам нужен еще больший контроль, вы можете использовать что-то вроде условия форсирования.

Ответ 2

Кстати, о TerminateThread(), используйте его таким образом.

DWORD exit_code= NULL;
if (thread != NULL)
{
    GetExitCodeThread(thread->m_hThread, &exit_code);
    if(exit_code == STILL_ACTIVE)
    {
        ::TerminateThread(thread->m_hThread, 0);
        CloseHandle(thread->m_hThread);
    }
    thread->m_hThread = NULL;
    thread = NULL;
}

Ответ 3

Вы должны подождать, пока поток не сделает все.

if(WaitForSingleObject(thread_handle, INFINITE) == WAIT_OBJECT_0) 
    ;//all right
else
    ;//report error

Остерегайтесь использования функции TerminateThread, это очень опасно.

Ответ 4

Сначала вам нужно запустить поток таким образом, чтобы MFC не удалял объект потока, когда он завершен, значение по умолчанию для MFC-поток должен удалить себя, поэтому вы хотите отключить его.

   m_thread = AfxBeginThread(ThreadProc, this, THREAD_PRIORITY_NORMAL ,CREATE_SUSPENDED);
   m_thread->m_bAutoDelete = FALSE;
   m_thread->ResumeThread();

Теперь в потоке вам нужен механизм, чтобы поток вызывающего абонента мог послать ему сигнал, чтобы закончить сам. Существует несколько способов, один из них - WaitForSingleObject для проверки состояния сигнала или другого способа - просто послать этому потоку сообщение, чтобы закончить сам. Это изящное окончание, скорее убивающее его.

Пока этот поток заканчивается сам (= выход из функции потока, очистка), вы можете заставить основной поток ждать его до завершения, прежде чем он выйдет.

     int wait = 2000 // seconds ( I am waiting for 2 seconds for worker to finish)
     int dwRes = WaitForSingleObject( m_thread->m_hThread, wait);
     switch (dwRes)
     {
     case WAIT_OBJECT_0:
         TRACE( _T("worker thread just finished") ); break;
     case WAIT_TIMEOUT:
         TRACE( _T("timed out, worker thread is still busy") ); break;
     }

Установка примечания m_bAutoDelete = FALSE выше позволяет нам иметь действительный дескриптор, когда поток заканчивается, поэтому мы можем ждать его. Последнее, что вы хотите сделать, это удалить объект CWinThread, чтобы освободить его память (поскольку мы взяли на себя ответственность за это).