Правильная очистка, если не удается закрыть поток - C ++ - PullRequest
4 голосов
/ 19 ноября 2010

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

_bCloseRequested = TRUE;
dwMsThen = ::GetTickCount();

do
{
    ::GetExitCodeThread( m_hThread, &dwExitCode );
    dwMsNow = ::GetTickCount();
}
while( (dwExitCode == STILL_ACTIVE) && ((dwMsNow - dwMsThen) < 50000UL) );

Если поток не может закрыться в течение 5 выделенных секунд, если дескриптор потока будетзакрыто или разрешено оставаться открытым?Спасибо.

Ответы [ 4 ]

6 голосов
/ 19 ноября 2010

Во-первых, не ждите окончания потока, как это.Вы просто израсходуете все доступное процессорное время, просто ожидая, что также имеет недостаток, заключающийся в том, что ваш поток займет больше времени!

Вместо этого используйте что-то вроде этого:Вы хотите оставить поток работающим или нет, зависит от того, что поток делает.Может ли он даже работать, даже если ваше главное приложение начинает делать что-то еще?Есть ли в нем критические вещи (файлы, соединения, базы данных, ...), которые были бы открыты, если бы вы убили поток?Вы должны обдумать все это, прежде чем решить, уничтожить ли поток или оставить его работающим.

2 голосов
/ 19 ноября 2010

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

static const DWORD TIMEOUT_VALUE(50000);

if (WaitforSingleObject(m_hThread, TIMEOUT_VALUE) != WAIT_OBJECT_0))
{
  // thread did not exit in time, log and exit process
}
1 голос
/ 19 ноября 2010

Хороший вопрос.

Есть несколько подходов к этому.

Первый подход - это то, что я считаю идеальным подходом.И это никогда не заканчивать темы.Причин для этого много, но вот несколько важных моментов:

  1. Если ваш поток владеет объектом синхронизации, он не будет освобожден
  2. У объектов RAII нет шансовочистить
  3. Выделенная память не будет освобождена
  4. Если вы находитесь в середине вызовов ядра Certian, вы можете использовать все ваше приложение

Итакпри таком подходе вы должны определить причины, по которым потоки не закрываются, и устранить эту проблему.Вы можете обнаружить, что проблемы уходят глубоко.Вы можете обнаружить тупики, условия гонки и т. Д. Статический анализ может помочь найти эти проблемы.

Идеальный подход - это тот, который вы всегда должны придерживаться.И при этом лучше не использовать спиновый замок.Вместо этого Wait () на дескрипторе потока с таймаутом.Вращаясь, вы тратите впустую ресурсы и крадете временные срезы из потока, который вы ждете.

Но в реальном мире, в производственном коде, вам нужна запасная мера на случай, если все остальное даст сбой.Сначала вы должны попробовать несколько методов, чтобы вызвать отключение потока.Если все не получается в крайнем случае, убить поток.Но из-за опасностей, связанных с убийством зомби, после того, как вы это сделаете, вам следует перезапустить все приложение.Когда вы уничтожаете поток, вы можете перевести процесс в недетерминированное состояние.Так что начните сначала.Зарегистрируйте сообщение об ошибке, закройте приложение и запустите снова.

0 голосов
/ 19 ноября 2010

Ни.Вы должны исправить все, что мешает завершению потока, и просто присоединиться к нему.Все остальное - просто взлом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...