Может ли TerminateThread() завершить GetCurrentThread()?

Документы не говорят, является ли результат GetCurrentThread() действительным аргументом для TerminateThread(), iow: может ли поток отменить себя.

Может это? И если да, то вернется ли TerminateThread() вообще?

Зачем это нужно нынешнему руководителю? Вы можете просто выйти из функции потока, что в любом случае также чище. В любом случае TerminateThread следует использовать только в крайнем случае.

wohlstad 09.07.2024 09:36

@wohlstad Это библиотека классов, класс Thread которой имеет метод завершения(). Как автор библиотеки, я не контролирую, как пользователи ее используют, но мне нужно иметь возможность поддерживать функции базовой ОС. pthread_cancel(pthread_self()) в порядке, поэтому мне просто интересно, нужно ли мне поддерживать или отклонять самозавершение.

Marc Mutz - mmutz 09.07.2024 13:57

«Я просто задавался вопросом, нужно ли мне поддержать или отвергнуть самоуничтожение». - Вы ДОЛЖНЫ отказаться от идеи вызвать TerminateThread(). «Как автор библиотеки, я не контролирую, как ее используют пользователи». Как автор библиотеки, вы имеете полную свободу действий в этом аспекте. Тривиальный пример: если вы не предоставляете функцию terminate() в своем общедоступном интерфейсе, клиенты не будут ее вызывать. Это буквально так просто. Это также не такой уж и дикий дизайнерский выбор: C++' std::thread и std::jthread не предоставляют общедоступный интерфейс для завершения потока, которым они управляют.

IInspectable 09.07.2024 15:56

@MarcMutz-mmutz, даже если вы по какой-то причине должны поддерживать API завершения (несмотря на комментарий выше), вы все равно можете проверить, является ли поток, который вам нужно завершить, текущим, и если да - вызовите ExitThread вместо TerminateThread что гораздо более жестоко.

wohlstad 09.07.2024 16:47

Между pthread_cancel и TerminateThread есть большая разница. pthread_cancel реализует кооперативную отмену, что означает, что объект ядра потока не уничтожается полностью. В теме даже разрешено игнорировать запрос на отмену от pthread_cancel. Однако использование TerminateThread похоже на закладку бомбы в ваш код. Вместо этого вы можете написать if (rand() < 10) ExitProcess(EXCEPTION_INVALID_HANDLE);.

Alex Veleshko 15.07.2024 15:22
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
132
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Но, похоже, это плохая идея:

  1. Вызов TerminateThread следует использовать только в крайнем случае.
    В приведенной выше ссылке на документацию есть много предостережений.
    Он также дает следующее резюме:

    TerminateThread — опасная функция, которую следует использовать только в самых крайних случаях.

  2. Есть гораздо лучшие способы упорядоченно завершить текущую ветку:
    (1). Возврат из функции потока — это лучший способ.
    (2). Вызовите ExitThread API.
    Обратите внимание, что в документации ExitThread проводится различие между кодом C++ и C:

    ExitThread — предпочтительный метод выхода из потока в коде C. Однако в коде C++ поток завершается до того, как можно будет вызвать какие-либо деструкторы или выполнить любую другую автоматическую очистку. Поэтому в коде C++ вам следует вернуться из функции потока.

Учитывая 2 пункта выше, я не вижу сценария, в котором вы хотели бы вызвать TerminateThread для текущей темы.

И последнее замечание:
Ссылаясь на ваш комментарий о библиотеке, которой, возможно, придется поддерживать API завершения потока:
Как упоминалось в комментарии, вам следует вообще не поддерживать API завершения (например, C++ std::thread его не поддерживает).
Если вам необходимо его поддержать, вы все равно можете проверить, является ли поток, который вам нужно прекратить, текущим, и если да, то вызовите ExitThread (упомянутый выше) вместо TerminateThread, что гораздо более жестоко.

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

Marc Mutz - mmutz 09.07.2024 13:59

@MarcMutz-mmutz Я не пытался читать тебе лекции. Ваш вопрос не содержал контекста вашего запроса, поэтому я подумал, что объяснение альтернативы может быть полезным. Я все еще считаю, что он содержит информацию, относящуюся к опубликованному вопросу.

wohlstad 09.07.2024 14:21

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

Marc Mutz - mmutz 11.07.2024 09:55

@MarcMutz-mmutz Я добавил реальный ответ, а также некоторую информацию об использовании библиотеки потоков, которую вы упомянули в комментарии. Еще раз хочу подчеркнуть, что поучать вас вовсе не мое намерение.

wohlstad 11.07.2024 12:19

@MarcMutz-mmutz Вы здесь не понимаете основ. Интерфейсы определяются с помощью предусловий и постусловий. Вызываемый объект гарантирует, что указанные постусловия выполняются до тех пор, пока выполняются предварительные условия. Это проверенная схема, которая позволяет клиентам передавать управление внешнему коду, сохраняя при этом локальные инварианты. Проблема в том, что TerminateThread() НЕТ ОПРЕДЕЛЕННЫХ ПОСЛОВИЙ. Вы вызываете его, и процесс, владеющий целевым потоком, мгновенно переходит в неопределенное состояние. Бесполезно спрашивать о гарантиях, если контракт о досрочном погашении их не предусматривает.

IInspectable 11.07.2024 18:34
Ответ принят как подходящий

Да, TerminateThread может завершить текущий поток. Результат GetCurrentThread имеет права THREAD_ALL_ACCESS, поэтому этот дескриптор тоже можно использовать.

Нет, TerminateThread в этом случае не вернется.

Нет, нет никаких причин когда-либо делать это! Не.

Однако обратите внимание, что GetCurrentThread() возвращает псевдодескриптор, а не настоящий дескриптор, который заметно отличается от возвращаемого значения CreateThread(). В любом случае вызывающий абонент имеет право доступа THREAD_ALL_ACCESS. Я просто указываю на это, поскольку ФП просит об одном, но затем продолжает объяснять, что они делают что-то другое.

IInspectable 09.07.2024 11:22

Другие вопросы по теме