Документы не говорят, является ли результат GetCurrentThread()
действительным аргументом для TerminateThread()
, iow: может ли поток отменить себя.
Может это? И если да, то вернется ли TerminateThread()
вообще?
@wohlstad Это библиотека классов, класс Thread которой имеет метод завершения(). Как автор библиотеки, я не контролирую, как пользователи ее используют, но мне нужно иметь возможность поддерживать функции базовой ОС. pthread_cancel(pthread_self()) в порядке, поэтому мне просто интересно, нужно ли мне поддерживать или отклонять самозавершение.
«Я просто задавался вопросом, нужно ли мне поддержать или отвергнуть самоуничтожение». - Вы ДОЛЖНЫ отказаться от идеи вызвать TerminateThread()
. «Как автор библиотеки, я не контролирую, как ее используют пользователи». Как автор библиотеки, вы имеете полную свободу действий в этом аспекте. Тривиальный пример: если вы не предоставляете функцию terminate()
в своем общедоступном интерфейсе, клиенты не будут ее вызывать. Это буквально так просто. Это также не такой уж и дикий дизайнерский выбор: C++' std::thread
и std::jthread
не предоставляют общедоступный интерфейс для завершения потока, которым они управляют.
@MarcMutz-mmutz, даже если вы по какой-то причине должны поддерживать API завершения (несмотря на комментарий выше), вы все равно можете проверить, является ли поток, который вам нужно завершить, текущим, и если да - вызовите ExitThread вместо TerminateThread
что гораздо более жестоко.
Между pthread_cancel
и TerminateThread
есть большая разница. pthread_cancel
реализует кооперативную отмену, что означает, что объект ядра потока не уничтожается полностью. В теме даже разрешено игнорировать запрос на отмену от pthread_cancel
. Однако использование TerminateThread
похоже на закладку бомбы в ваш код. Вместо этого вы можете написать if (rand() < 10) ExitProcess(EXCEPTION_INVALID_HANDLE);
.
Чтобы ответить на ваш непосредственный вопрос:
Поскольку документы не запрещают вызывать TerminateThread
из текущего потока, я делаю вывод, что допустимо использование любого дескриптора потока, включая текущий.
В этом случае, поскольку поток всегда завершается до возврата TerminateThread
, он никогда не вернется к вызывающей стороне.
Но, похоже, это плохая идея:
Вызов TerminateThread следует использовать только в крайнем случае.
В приведенной выше ссылке на документацию есть много предостережений.
Он также дает следующее резюме:
TerminateThread — опасная функция, которую следует использовать только в самых крайних случаях.
Есть гораздо лучшие способы упорядоченно завершить текущую ветку:
(1). Возврат из функции потока — это лучший способ.
(2). Вызовите ExitThread API.
Обратите внимание, что в документации ExitThread
проводится различие между кодом C++ и C:
ExitThread — предпочтительный метод выхода из потока в коде C. Однако в коде C++ поток завершается до того, как можно будет вызвать какие-либо деструкторы или выполнить любую другую автоматическую очистку. Поэтому в коде C++ вам следует вернуться из функции потока.
Учитывая 2 пункта выше, я не вижу сценария, в котором вы хотели бы вызвать TerminateThread
для текущей темы.
И последнее замечание:
Ссылаясь на ваш комментарий о библиотеке, которой, возможно, придется поддерживать API завершения потока:
Как упоминалось в комментарии, вам следует вообще не поддерживать API завершения (например, C++ std::thread
его не поддерживает).
Если вам необходимо его поддержать, вы все равно можете проверить, является ли поток, который вам нужно прекратить, текущим, и если да, то вызовите ExitThread
(упомянутый выше) вместо TerminateThread
, что гораздо более жестоко.
Спасибо, но мне не нужно читать лекции об обоснованности вопроса. Это не ответ на мой вопрос, предлагаю в следующий раз вместо этого использовать комментарии.
@MarcMutz-mmutz Я не пытался читать тебе лекции. Ваш вопрос не содержал контекста вашего запроса, поэтому я подумал, что объяснение альтернативы может быть полезным. Я все еще считаю, что он содержит информацию, относящуюся к опубликованному вопросу.
справедливо, но я уже дал ссылку на документацию по функции и спросил об одном аспекте, на который документы не отвечают. Этот ответ просто повторяет то, что уже сказано в связанных документах. Это было бы нормально... если бы это также отвечало на реальный вопрос.
@MarcMutz-mmutz Я добавил реальный ответ, а также некоторую информацию об использовании библиотеки потоков, которую вы упомянули в комментарии. Еще раз хочу подчеркнуть, что поучать вас вовсе не мое намерение.
@MarcMutz-mmutz Вы здесь не понимаете основ. Интерфейсы определяются с помощью предусловий и постусловий. Вызываемый объект гарантирует, что указанные постусловия выполняются до тех пор, пока выполняются предварительные условия. Это проверенная схема, которая позволяет клиентам передавать управление внешнему коду, сохраняя при этом локальные инварианты. Проблема в том, что TerminateThread()
НЕТ ОПРЕДЕЛЕННЫХ ПОСЛОВИЙ. Вы вызываете его, и процесс, владеющий целевым потоком, мгновенно переходит в неопределенное состояние. Бесполезно спрашивать о гарантиях, если контракт о досрочном погашении их не предусматривает.
Да, TerminateThread
может завершить текущий поток. Результат GetCurrentThread
имеет права THREAD_ALL_ACCESS
, поэтому этот дескриптор тоже можно использовать.
Нет, TerminateThread
в этом случае не вернется.
Нет, нет никаких причин когда-либо делать это! Не.
Однако обратите внимание, что GetCurrentThread()
возвращает псевдодескриптор, а не настоящий дескриптор, который заметно отличается от возвращаемого значения CreateThread()
. В любом случае вызывающий абонент имеет право доступа THREAD_ALL_ACCESS
. Я просто указываю на это, поскольку ФП просит об одном, но затем продолжает объяснять, что они делают что-то другое.
Зачем это нужно нынешнему руководителю? Вы можете просто выйти из функции потока, что в любом случае также чище. В любом случае
TerminateThread
следует использовать только в крайнем случае.