Завершение рабочего потока в MFC
Как правильно завершить рабочий поток, если его завершение занимает слишком много времени? Я прочитал несколько статей, утверждающих, что TerminateThread следует использовать с особой осторожностью, но я не могу найти какой-либо жизнеспособной альтернативы.
Псудо-код:
void CMyDialog::RunThread()
{
CWinThread* pThread; // pointer to thread
DWORD dwWaitResult; // result of waiting for thread
// start thread
pThread = AfxBeginThread(beginThread, this,
THREAD_PRIORITY_NORMAL,
0,
CREATE_SUSPENDED);
pThread->m_bAutoDelete = FALSE;
pThread->ResumeThread();
// wait for thread to return
dwWaitResult = ::WaitForSingleObject(pThread->m_hThread, (30 * 1000));
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
delete pThread;
// success, continue
break;
case WAIT_TIMEOUT:
// thread taking too long, terminate it
TerminateThread(pThread->m_hThread, 0);
delete pThread;
break;
} // end switch on wait result
}
UINT CMyDialog::beginThread(LPVOID pParam)
{
// convert parameter back to dialog object and call method
CMyDialog* dlg = (CMyDialog*) pParam;
dlg->readDuration();
return 0;
} // end beginThread
void CMyDialog::readDuration()
{
// call a dll function that may take longer than we are prepared to wait,
// or even hang
} // end readDuration
Это приемлемо? Все комментарии и предложения с благодарностью получены.
Я использую MFC/C++ в Visual Studio 2008. Разрабатываю для Vista, ориентируясь на XP, Vista и 7.
2 ответа
Небезопасно прерывать поток, как уже упоминала Саня. Типичным решением в таких случаях является порождение дочернего процесса, единственной ролью которого является размещение DLL и вызов метода (ов). Ваш основной процесс будет взаимодействовать с дочерним процессом через некоторый механизм LPC, чтобы передать аргументы для вызова метода DLL и вернуть результат. По таймауту совершенно безопасно убить дочерний процесс, ядро вернет все ресурсы, и не будет утечек в памяти или системных объектах (хотя могут сохраняться утечки на диске, как, например, файлы, оставшиеся). Это значительно сложнее, чем просто вызов DLL (вам нужно будет найти решение для межпроцессного взаимодействия), но это единственный надежный способ.
Плохая идея использовать TerminateThread - это небезопасно и может вызвать некоторые утечки. Вы можете использовать события, чтобы сообщить об окончании потока. Несколько полезных ссылок
Хороший ответ о прекращении темы здесь