Проверьте, запущен ли поток Win32 или приостановлен

Как проверить, работает ли поток Win32 или находится в приостановленном состоянии?

Я не могу найти Win32 API, который дает состояние потока. Итак, как мне получить состояние потока?

8 ответов

Решение

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

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

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

Мораль истории - если вы хотите знать, что поток приостановлен, - приостановите его: возвращаемое значение из SuspendThread - это предыдущий счетчик приостановки потока. И теперь вы знаете что-то полезное - поток был и остается приостановленным - что полезно. Или что это не было (но сейчас) приостановлено. В любом случае, состояние потока теперь известно детерминистически, поэтому теоретически вы можете сделать несколько разумных решений на основе этого - либо ResumeThread, либо оставить его приостановленным.

Вы можете получить эту информацию, вызвав NtQuerySystemInformation() со значением для SystemProcessesAndThreadsInformation (целочисленное значение 5).

Если вам нужен пример того, что вы можете сделать с этой информацией, взгляните на Thread Status Monitor.

Хотя это не задокументировано - хотя это должно быть ИМХО, если вы вызываете WaitForSingleObject, он вернет WAIT_ABANDONED, если поток приостановлен. Кроме того, если поток завершен, его дескриптор будет в сигнальном состоянии.

Больше всего меня беспокоит, когда кто-то отвечает на ваши вопросы, говоря, почему у вас не должно быть ответа на ваш вопрос... Или начинает задавать вопросы, ПОЧЕМУ вы хотите это сделать. Когда кто-то находит этот вопрос в Google, причины, по которым ПОЧЕМУ не совпадают, и, таким образом, ответ сделает его бесполезным для кого-либо еще.

Класс WMI Win32_Thread имеет ThreadState собственность, где 5: "Приостановлено заблокировано" и 6: Приостановлено Готово.

Вам понадобится идентификатор потока, чтобы получить правильный экземпляр напрямую (свойство Handle объекта WMI является идентификатором потока).

РЕДАКТИРОВАТЬ: учитывая этот запрос PowerShell:

gwmi win32_thread | group ThreadState

дает

Название группы
----- ---- -----
    6 2 {,,,...}
  966 5 {,,,...}

WMI имеет другое определение "Приостановлено" для Win32.

Вы могли бы получить счетчик приостановки потока с кодом как это:

DWORD GetThreadSuspendCount(HANDLE hThread) {
    DWORD dwSuspendCount = SuspendThread(hThread);
    ResumeThread(hThread);
    return dwSuspendCount;
}

но, как уже говорилось - это не точно. Более того, приостановка потока - это зло.

ДА: возможно получить состояние потока и определить, приостановлено ли оно.

И НЕТ: вам не нужна Windows 7 для этого.

Я опубликовал свой рабочий класс здесь на Stackru: как получить состояние потока (например, приостановлено), использование памяти + ЦП, время запуска, приоритет и т. Д.

Этот класс требует Windows 2000 или выше.

В Windows 7 вы можете использовать QueryUmsThreadInformation. (UMS означает планирование в режиме пользователя).

Смотрите здесь для UmsThreadIsSuspended,

Я думаю, что государство здесь упоминается как

  • Если поток находится в потоке, выполняющий некоторую обработку или
  • В ожидании события

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

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

К сожалению, нет. В зависимости от вашего кода, вы можете приблизиться к этому (устанавливая флаг всякий раз, когда вы, например, ожидаете объект ядра), но имейте в виду, что поток всегда может блокировать вызовы ОС или библиотеки, и вы не будете знать об этом.

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