Страницы

Поиск по вопросам

пятница, 27 декабря 2019 г.

Как лучше всего убить зависший поток?

#cpp #visual_cpp #многопоточность #потоки_данных


std::thread * tr1;
tr1 = new std::thread([&]()
{
    function();     // функция что то считает
    Sleep(3000000); // допустим это означает зависание
});


Запущенный поток по каким то причинам завис, таймер определил, что поток выполняется
дольше времени. Как можно убить поток, чтобы он не висел в памяти и не выполнял вычисления?
В потоке нет никаких мьютексов и.т.д.  Никакие переменные разрушится не смогут, туда
передаётся указатель, который при обнаружении что таймер превышен задается в ноль.
Больше поток ни с кем и ни с чем не контактирует. 

Как его можно убить или поставить на паузу?
    


Ответы

Ответ 1



Если на винде, то TerminateThread(tr1->native_handle,0); используйте на свой страх и риск :D

Ответ 2



std::thread не поддерживает данную фичу, потому что так делать крайне не рекомендуется. Если у вас повис поток, это уже плохо, и именно эту проблему надо исправлять, а не пытаться городить костыли с убийствами потоков. Если в потоке выполняется ваш код, то периодически проверяйте флаг выхода из потока или воспользуйтесь другим способом синхронизации. Если выполняется не ваш код, то ни в коем случае не трогайте поток. Никто не знает, что может оказаться в чужом коде. Если вам нужны убиваемые потоки, то можете воспользоваться boost::thread. Или доковыряться до нативного хэндла std::thread::naitive_handle и воспользоваться специфичными для оси функциями.

Ответ 3



Потоки убивать нельзя. Поток взаимодействует с другими потоками, которые могут ждать каких то действий от убиваемого потока и убийство приведёт к взаимоблокировке (deadlock). Например: второй поток ждёт вызова SetEvent(), которого не произойдёт. Поток может умереть и оставить текущий объект в несогласованном состоянии, что приведёт к неопределённому дальнейшему поведению программы. Поток может работать с файлом, который так же останется в несогласованном состоянии (запись не будет завершена и файл будет испорчен). Как правило у длительных блокирующих операций ввода-вывода есть возможность прервать выполнение, вызывать их асинхронно, использовать неблокирующее API и т.п. Например: вызывать select или poll с коротким временем ожидания, и в цикле проверять не пришёл ли запрос на остановку. Можно открыть pipe и добавить его дескриптор в набор FD_SET для select() и когда понадобиться написать что нибудь в pipe для возврата из вызова select().

Ответ 4



если очень хочется то можно вызвать деструктор объекта, например используя умный указатель, код будет выглядить примерно так: std::unique_ptr tr1 (new std::thread([&]() { function(); // функция что то считает Sleep(3000000); // допустим это означает зависание })); if( tr1.joinable() ) // проверим, что поток запущен tr1.clear(); // в деструкторе потока вызовится метод terminate() документация

Комментариев нет:

Отправить комментарий