Как закрыть поток c
Перейти к содержимому

Как закрыть поток c

  • автор:

pthreads завершить поток

Привет. Помогите, плиз, с потоками, а то оно всё какое-то страшное. Надо выполнить гарантированное завершение потока, и при этом не завесить «управляющий» поток. То есть, пусть в потоке крутится какой-то цикл, и опрашивает переменную ThreadTerminated, при установке которой в 1 поток благополучно завершается сам. Тут вопросов нет. Но если вдруг этот поток где-то внутри завис, на такой случай не пойму как это проверить и завершить. Под виндами я делал примерно так:

if WaitForSingleObject(hThread, 5000) = WAIT_TIMEOUT then TerminateThread(hThread);

И всё. Если поток нормально работает, то он быстренько проверит значение ThreadTerminate и «умрет» самостоятельно. Если же он висит, то через 5 секунд будет прибит принудительно, но главное — поток в котором приведенный код выполняется, так или иначе, продолжит работу, а поток hThread будет, так или иначе, завершен.

Ближайший аналог в pthreads, который я нашел — это pthread_join(thread, value). Но тайм-аут в нем не предусмотрен, т.е. если поток положил большой болт на значение ThreadTerminate, то при выполнении pthread_join() повиснет и этот, вызвавший функцию, поток. А если join не делать, то есть вероятность, что тот поток так и продолжит висеть. Можно, конечно, вызвать pthread_cancel(), но для этого надо знать, что поток самостоятельно умирать не желает. А как это проверить без join?

Прервать C++ поток

Пусть имеется класс, выполняющий запуск некоторой работы в потоке:

void MyThread::run() < if (!ThreadPtr) < ThreadPtr = new std::thread(&MyThread::realWork, this); ThreadPtr->detach(); > > 

При этом при этом realWork содержит вызов некоторой долгоработающей функции из сторонней библиотеки

MyThread::realWork()

Как можно прервать запущенный поток? Корректно ли просто сделать delete?

void MyThread::break() < if (ThreadPtr) < delete ThreadPtr; ThreadPtr=null; >> 

clanproger
06.02.20 12:12:11 MSK

std::terminate() не катит?

Unicode4all ★★★★★
( 06.02.20 12:23:42 MSK )

В с++ нет такого API, используй pthread или, лучше, отдельный процесс.

filosofia ☆
( 06.02.20 12:26:27 MSK )

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

Ну либо использовать процессы, тогда ОС уберёт оставленный мусор.

invy ★★★★★
( 06.02.20 12:34:47 MSK )
Последнее исправление: invy 06.02.20 12:36:33 MSK (всего исправлений: 1)

Ответ на: комментарий от invy 06.02.20 12:34:47 MSK

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

filosofia ☆
( 06.02.20 12:41:13 MSK )
Ответ на: комментарий от invy 06.02.20 12:34:47 MSK

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

yoghurt ★★★★★
( 06.02.20 12:59:01 MSK )

Кажись и вправду нет такого API в самом С++. На Linux’е можно юзать pthread_cancel, предварительно вызвав std::thread::native_handle.

Nibbler
( 06.02.20 13:32:58 MSK )

you are doing it wrong. Поток должен завершится без внешнего API. По сообщению/флагу/… за pthread_cancel как способ «штатного» завершения тоже надо бить ногами.

anonymous
( 06.02.20 14:43:03 MSK )

Какую задачу ты решаешь? Скорее всего, потоки тебе не нужны.

DELIRIUM ☆☆☆☆☆
( 06.02.20 16:20:10 MSK )

Прерывать поток – антипаттерн.

Reset ★★★★★
( 06.02.20 16:51:39 MSK )
Ответ на: комментарий от Nibbler 06.02.20 13:32:58 MSK

Кажись и вправду нет такого API в самом С++.

И в портабельном glib тоже нет, что намекает на неоправданно большое количество подводных камней такого подхода.

gag ★★★★★
( 06.02.20 17:11:02 MSK )
Ответ на: комментарий от Nibbler 06.02.20 13:32:58 MSK

Кажись и вправду нет такого API в самом С++

fsb4000 ★★★★★
( 06.02.20 17:22:07 MSK )
Ответ на: комментарий от Reset 06.02.20 16:51:39 MSK

Если на то пошло, многопоточность — антипаттерн 🙂 Только параллелизм по данным, только корутины, CSP. и MIMD, только хардкор!

slackwarrior ★★★★★
( 06.02.20 17:37:51 MSK )
Ответ на: комментарий от slackwarrior 06.02.20 17:37:51 MSK

Using threads for performance reasons is an AntiPattern. At least when done without significant profiling which identifies serialization as a bottleneck.

Дальше не читал. Бред синьор энтерпрайз жаба кодера, который делает только CRUD и других задач и не видел никогда.

CatsCantFly ★
( 06.02.20 21:14:59 MSK )
Ответ на: комментарий от CatsCantFly 06.02.20 21:14:59 MSK

Плохо ты читал. Там как раз про то, что джава тоже не нужна для параллелизма. И еще про массовое заблуждение «что потоки — это ускорение». Про закон Амдала тоже не все слышали, кто слышал что «прерывать поток — это антипаттерн» 🙂

slackwarrior ★★★★★
( 06.02.20 21:20:58 MSK )
Последнее исправление: slackwarrior 06.02.20 21:23:42 MSK (всего исправлений: 2)

Когда делаешь delete, не нужно проверять на нулевой указатель. А по теме — посылаешь сообщение и по этому сообщению прерываешь поток изнутри. Либу придется пропатчить.

anonymous
( 06.02.20 21:21:24 MSK )

точки отмены/прерывания пока не стандартизированный, поэтому на чистом c++ никак не влезая в логику функции потока.

pon4ik ★★★★★
( 06.02.20 22:34:37 MSK )
Ответ на: комментарий от Reset 06.02.20 16:51:39 MSK

То то в POSIX про это столько фишечек.

На самом деле, кейс, когда это и правда хорошая идея довольно редок, правильнее даже сказать исчезающе редок, но тем не менее, их есть.

Например дескриптор не поддерживает неблокирующий режим, а как-то по таймауту его i/o таки надо прервать.

pon4ik ★★★★★
( 06.02.20 22:37:36 MSK )
Ответ на: комментарий от pon4ik 06.02.20 22:37:36 MSK

То то в POSIX про это столько фишечек.

И что? Половина POSIX’а состоит из костылей и подпорок.

Например дескриптор не поддерживает неблокирующий режим, а как-то по таймауту его i/o таки надо прервать.

Что за дескриптор? Откуда взялся? Почему не поддерживает?

Reset ★★★★★
( 06.02.20 22:51:56 MSK )
Ответ на: комментарий от anonymous 06.02.20 14:43:03 MSK

за pthread_cancel как способ «штатного» завершения тоже надо бить ногами.

Объясни безграмотному, почему. Только без токсичности.

Nibbler
( 07.02.20 12:20:42 MSK )
Ответ на: комментарий от fsb4000 06.02.20 17:22:07 MSK

Благодарю за инфу.

Nibbler
( 07.02.20 12:26:12 MSK )
Ответ на: комментарий от CatsCantFly 06.02.20 21:14:59 MSK

Дальше не читал. Бред синьор энтерпрайз жаба кодера, который делает только CRUD и других задач и не видел никогда.

Да ваще лох! В 2020 увеличение производительности даже дисков/сети идёт почти линейное до 8-16, а то и больше тасков. А ещё полезно разбивать куски большого кода на поменьше, чтобы они в L2 хотя бы влазили, и собирать из них конвейер. Чувак высокопроизводительный код просто не писал никогда.

mv ★★★★★
( 07.02.20 17:08:13 MSK )
Ответ на: комментарий от mv 07.02.20 17:08:13 MSK

Вы там все между строк пронзаете, нелохи, и читаете поверхам: At least when done without significant profiling which identifies serialization as a bottleneck. Типичное «искажение подтверждения». Потоки нифига не серебряная пуля, хоть в 2020-м, хоть когда. А «кэшфрендлинесс» с влезанием в L2 и прочая «локалити» тут ортогональна – против нее никто не возражает. Алсо, там перечисляются N точек зрения с «за» и «против» многопоточности, которой надо находить оправлание в конкретных задачах.

Чувак высокопроизводительный код просто не писал никогда.

Сдувайте щоки. Без описания критериев «производительности» конкретной задачи, численных прикидок теоретического выигрыша и, самое главное, сравнительного профайлинга на конкретном железе, т.е. пруфов этого твоего «высокопроизводительного кода» это просто треп и бузворды (а еще часто «хабитуал слоптимизейшон», потому что «модно» или «уважать перестанут» если не применишь все заявленные буззворды – именно так за припонтованными теоретиками часто тихо вычищают глючное «многопоточное» карго-гуано там где справляется простой бэкграунд-воркер или выпиливают навязанную ими без понимания нужности «неблокирующую очередь», после которой все упирается в коннектор к базе, в котором все «высокопроизводительно-неблокирующее» успешно отдыхает на мьютексе, низводя преимущества неблокирующей очереди не до нуля, а в минуса – с учетом потраченного времени на ее выпиливание).

anonymous
( 08.02.20 09:21:21 MSK )
Ответ на: комментарий от anonymous 08.02.20 09:21:21 MSK

Поток сознания не дочитал, но при всём правильном написанном коде со времён Нехалема единственный способ хоть как-то ускориться — это натягивать код на многоядерность. Потому что производительность одного ядра на гигигерц никак особо не изменилась.

Как принудительно завершить поток?

С помощью async запускаю в main поток, в котором крутится бесконечный цикл. Как завершить этот поток?

Отслеживать
Andrej Levkovitch
задан 26 апр 2018 в 11:25
Andrej Levkovitch Andrej Levkovitch
8,027 2 2 золотых знака 19 19 серебряных знаков 45 45 бронзовых знаков
добавить фалг выхода из бесконечного цикла.
26 апр 2018 в 11:28

Варианты: 1. добавить всётаки флаг. Обнулять извне. 2. Делать потоку terminate. 3. Завершить процесс через terminate — тогда завершится всё.

26 апр 2018 в 11:31

Скорее автору надо определится, что он хочет — иметь бесконечный цикл или иметь возможность завершать его. Это взаимоисключающие варианты.

26 апр 2018 в 11:35

Бесконечный цикл, с точки зрения языка С++, является неопределённым поведением. Поэтому добавляйте условие выхода и используйте его.

26 апр 2018 в 12:01

@AndrejLevkovitch ну тогда да, заведите флаг завершения потока, защитите доступ к нему с помощью, например, std::mutex , и заваршайте цикл по флагу. А снаружи после изменения флага делайте std::join

26 апр 2018 в 12:44

2 ответа 2

Сортировка: Сброс на вариант по умолчанию

*.pro файл для QtCreator:

TEMPLATE = app CONFIG += console c++11 CONFIG -= app_bundle CONFIG -= qt LIBS += -lpthread SOURCES += main.cpp 
#include #include #include #include #include #include using namespace std; bool ExitFlag = false; int someVariable = 0; std::mutex threadMutex; void threadFunc() < while (true)< std::this_thread::sleep_for(std::chrono::seconds(1)); someVariable = std::rand() % 100; std::cout > > int main()
var:83 var:86 var:77 var:15 var:93 var:35 var:86 var:92 var:49 var:21 Hello World! 

Завершение потока

Завершение потока
Как завершить поток из main чтобы все потом нормально было.

Завершение потока ввода
Всем привет,столкнулся с небольшой проблемой,расскажите почему так происходит собственно.. сама.

Правильное завершение потока при фатальной ошибке
Создаю поток через CreateThread(. ), поток выполняется и в какой то момент в нем происходит.

Вызывть метод одного потока из другого потока
Здравствуйте, подскажите пожалуйста, как можно реализовать такую штуку : есть один поток(1).

Эксперт С++

8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562

Нельзя завершить тред не join-ом. Если вызвали detach — поток уже никак не достать (по крайней мере средствами стандартной библиотеки).
http://stackoverflow.com/quest. ead-object
http://stackoverflow.com/quest. ead-in-c11

Регистрация: 09.09.2014
Сообщений: 182

Если я правильно понимаю, нужно объявить флаг доступный и для мейна, и для треда. Проверять положение флага в треде при каждой итерации цикла. Менять флаг в мейне на false, чтобы тред завершил цикл и вышел из функции. Флаг = bool.

P.s. мне тоже интересен этот вопрос.

Эксперт по математике/физикеЭксперт С++

2019 / 1347 / 384
Регистрация: 16.05.2013
Сообщений: 3,475
Записей в блоге: 6

Поток завершается при достижение конца блока функции выполнения или одного из return’ов.
Теперь вопрос: хотите ли вы управлять потоком из главного потока или поток сам должен определять свое завершение.
Если первое то следует использовать условные переменные и присоеденять поток к основному. Иначе вы можете столкнуться с проблемой обращения к недействительным переменным (они же условные переменные).
Если второе то return вам в помощь.

Регистрация: 12.10.2011
Сообщений: 784

Ну если функция возвращает false то в принципе можно завершить поток void nev() вопрос а завершится ли при этом void ne1v()? и второе если в потоке void nev1() настал момент когда эти 2 потока уже не нужны то его то можно завершить ретурном а как завершить поток void nev()? без проверки каких либо переменных в цикле? а по ID потока например. или вариант только с постоянной проверкой каких то флагов?

Добавлено через 1 минуту
Если не отсоединять поток то как я понял в первом потоке цикл не будет выполнятся? У меня во всех 3-х потоках циклы которые что то делают и возникают такие условия когда они уже не нужны
а в main опять же по условиям в цикле вызываются все новые потоки.

1 2 3 4 5 6 7 8 9 10
void main () { //какой то код. do { std::thread th_nev (nev);//запускаем поток nev.detach (); //какой то код. }while(true) }

Регистрация: 09.09.2014
Сообщений: 182

Вы уверены, что вам вообще нужны потоки? А то как то странно, вы создаете потоки в цикле, ещё и не запоминаете их.

Регистрация: 12.10.2011
Сообщений: 784
Это сервер.

1 2 3 4 5 6 7 8 9 10 11
void main () { //какой то код. do { //какой то код. std::thread th_nev (nev);//запускаем поток nev.detach (); }while(true) }

здесь мы ждем новых подключившихся клиентов. и при подключении запускаем отдельный поток для клиента и ждем следующего.

Добавлено через 1 минуту
void nev() — здесь обрабатываю данные полученные с клиента до его дисконнекта.

Добавлено через 2 минуты
поток void nev1() нужен для получения данных от других клиентов не зависимо от вызвавшего его потока следовательно при дисконнекте этот поток тоже становится не нужен, но если void nev() еще можно закрыть ретурном то как быть с void nev1()?

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *