Завершение рабочего потока в MFC - PullRequest
4 голосов
/ 15 августа 2011

Как правильно завершить рабочий поток, если его завершение занимает слишком много времени? Я прочитал несколько статей, утверждающих, что 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 ]

1 голос
/ 15 августа 2011

Опасно прерывать поток, как уже упоминал Саня.Типичным решением в таких случаях является порождение дочернего процесса, единственной ролью которого является размещение DLL и вызов метода (ов).Ваш основной процесс будет взаимодействовать с дочерним процессом через некоторый механизм LPC, чтобы передать аргументы для вызова метода DLL и вернуть результат.По таймауту совершенно безопасно убить дочерний процесс, ядро ​​вернет все ресурсы, и не будет утечек в памяти или системных объектах (хотя могут сохраняться утечки на диске, как, например, файлы, оставшиеся).Это значительно сложнее, чем просто вызвать DLL (вам нужно будет найти решение для межпроцессного взаимодействия), но это единственный надежный способ.

1 голос
/ 15 августа 2011

Плохо использовать TerminateThread, поскольку он небезопасен и может вызвать некоторые утечки.Вы можете использовать события, чтобы сообщить об окончании потока.Некоторые полезные ссылки

  1. http://www.codeproject.com/KB/threads/Synchronization.aspx

  2. http://msdn.microsoft.com/en-us/library/ms686915(v=vs.85).aspx

Хороший ответ о прекращении потока здесь

...