Как создать новый поток и завершить его через некоторое время?

Сделка:

Я хочу создать поток, который работает аналогично выполнению нового.exe в Windows, поэтому, если эта программа (новый поток) выйдет из строя или перейдет в бесконечный цикл: она будет убита изящно (после превышения лимита времени или при его сбое) и все ресурсы освобождены должным образом.

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

Изменить: Уточнить проблему намного больше.

6 ответов

Нить - это не какой-то волшебный объект, который можно заставить делать. Это отдельный путь выполнения вашего кода. Ваш код не может произвольно перемещаться вокруг своей базы кода, если вы специально не запрограммируете его для этого. И даже тогда это можно сделать только в рамках правил C++ (т.е. Вызывающих функций).

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

Это не похоже на обработку исключений, где C++ специально требует вызова деструкторов, и у вас есть возможность ловить исключения и выполнять специальную очистку. Вы говорите о выполнении одного фрагмента кода, а затем неожиданно прекращаете выполнение всего этого стека вызовов. Это не сработает.

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

Когда процесс завершается и устанавливает его данные, вам нужно использовать некоторую систему межпроцессной связи для чтения этих данных (мне нравится Boost.Interprocess). Он не будет выглядеть как обычная глобальная переменная C++, но вы не должны иметь проблемы с ее чтением. Таким образом, вы можете эффективно убить процесс, если он занимает слишком много времени, и ваша программа останется в разумном состоянии.


Поток уже запускается после вызова CreateThread.

WaitForSingleObject не требуется (если вы действительно не хотите дождаться окончания потока); но он не будет "принудительно покидать" нить; на самом деле, отказ от власти - даже если это возможно - никогда не бывает такой хорошей идеей; вы можете, например, оставить ресурсы открытыми или иным образом оставить свое приложение в состоянии, которое не подходит.


Ну, что делает WaitForSingleObject. Он блокируется до тех пор, пока объект ничего не сделает (в случае потока он ждет, пока поток не выйдет или тайм-аут не истечет). Что вам нужно

HANDLE thread = CreateThread(0, 0, do_stuff, NULL, 0, 0);
//rest of code that will run paralelly with your new thread.
WaitForSingleObject(thread, 4000); // wait 4 seconds or for the other thread to exit


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

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

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

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


Удалить вызов WaitForSingleObject?


Удалите вызов WaitForSingleObject. Это заставляет родительский поток ждать.

licensed under cc by-sa 3.0 with attribution.