как проверить жив ли поток (TThread)
От: srid  
Дата: 29.05.06 10:46
Оценка:
запущен поток на базе класса TThread

как проверить, существует(выполняется) ли он, или его кто-то грохнул?
Re: как проверить жив ли поток (TThread)
От: Danchik Украина  
Дата: 29.05.06 10:54
Оценка:
Здравствуйте, srid, Вы писали:

S>запущен поток на базе класса TThread


S>как проверить, существует(выполняется) ли он, или его кто-то грохнул?


Это как это кто то грохнул?
Вы что в своей программе не можете лад навести?
Поток умирает когда заканчивается выполнение Execute. А обьект TThread умирает когда ему вызвать Free или проставить FreeOnTerminate := True.
Остальное это игры c WinAPI, о которых будет сказано только после того как вы более понятно напишете для чего это нужно.
Re[2]: как проверить жив ли поток (TThread)
От: srid  
Дата: 29.05.06 11:50
Оценка:
S>>запущен поток на базе класса TThread
S>>как проверить, существует(выполняется) ли он, или его кто-то грохнул?

D>Это как это кто то грохнул?

D>Вы что в своей программе не можете лад навести?
не делайте поспешных выводов

D>Поток умирает когда заканчивается выполнение Execute. А обьект TThread умирает когда ему вызвать Free или проставить FreeOnTerminate := True.

D>Остальное это игры c WinAPI, о которых будет сказано только после того как вы более понятно напишете для чего это нужно.

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

поиски по заданному вопросу меня никчему не привели (как и эксперименты).
из ситуации вышел другим способом, но ответ на вопрос по прежнему интересен.
Re[3]: как проверить жив ли поток (TThread)
От: Danchik Украина  
Дата: 29.05.06 12:06
Оценка: 2 (1)
Здравствуйте, srid, Вы писали:

[Skip]

S>ок.

S>в потоке выполняются разные действия по защите программы (от копирования).
S>конечному пользователю, естественно, это может не понравиться.
S>и он _может_ убить его сторонними программами.
S>вот, хотелось бы отследить такой вариант.

S>поиски по заданному вопросу меня никчему не привели (как и эксперименты).

S>из ситуации вышел другим способом, но ответ на вопрос по прежнему интересен.

Запоминаем хендл потока — TThread.Handle
C помощью функции WaitForSingleObject(Handle, 1) <> Timeout — с потоком что то случилось. Правда этот вариант не совсем корректен по словам из MSDN.

Можна попробовать еще один вариант:
uses
  TlHelp32
...
var
  aSnapProcHandle: THandle;
  aThreadEntry: TThreadEntry32;
  aCurrentProcessID : Cardinal;
  aThreadHandle : Cardinal;
  aNext: Boolean;
begin
  aSnapProcHandle := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
  if aSnapProcHandle <> THandle(-1) then
  try
    aCurrentProcessID  := GetCurrentProcessId;
    aThreadEntry.dwSize := Sizeof(aThreadEntry);
    aNext := Thread32First(aSnapProcHandle, aThreadEntry);
    while aNext do begin
      if aThreadEntry.th32OwnerProcessID = aCurrentProcessID then begin
        { наши потоки }
      end;
      aNext := Thread32Next(aSnapProcHandle, aThreadEntry);
    end;
  finally
    CloseHandle(aSnapProcHandle);
  end;
end;

В даном примере перебираются все потоки процеса. Если мы не нашли наш — досвидания
Re[4]: как проверить жив ли поток (TThread)
От: srid  
Дата: 29.05.06 16:42
Оценка:
D>Запоминаем хендл потока — TThread.Handle
D>C помощью функции WaitForSingleObject(Handle, 1) <> Timeout — с потоком что то случилось. Правда этот вариант не совсем корректен по словам из MSDN.

проверил — супер
а почему так может быть не корректно?
(в MSDN про некорректность не нашел, если не трудно — процитируйте)


D>Можна попробовать еще один вариант:

до второго варианта не добрался
Re[3]: как проверить жив ли поток (TThread)
От: ekamaloff Великобритания  
Дата: 30.05.06 06:05
Оценка:
Здравствуйте, srid, Вы писали:

S>из ситуации вышел другим способом, но ответ на вопрос по прежнему интересен.


function CheckThreadIsAlive(Thread: TThread): Boolean;
begin
    Result := WaitForSingleObject(Thread.Handle, 0) = WAIT_OBJECT_0;
end;
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Re[5]: как проверить жив ли поток (TThread)
От: Danchik Украина  
Дата: 30.05.06 07:42
Оценка:
Здравствуйте, srid, Вы писали:

D>>Запоминаем хендл потока — TThread.Handle

D>>C помощью функции WaitForSingleObject(Handle, 1) <> Timeout — с потоком что то случилось. Правда этот вариант не совсем корректен по словам из MSDN.

S>проверил — супер

S>а почему так может быть не корректно?
S>(в MSDN про некорректность не нашел, если не трудно — процитируйте)

Вот выдержка из MSDN:

Parameters
hHandle
[in] Handle to the object. For a list of the object types whose handles can be specified, see the following Remarks section.
If this handle is closed while the wait is still pending, the function's behavior is undefined.

The handle must have the SYNCHRONIZE access right. For more information, see Standard Access Rights.

dwMilliseconds
[in] Time-out interval, in milliseconds. The function returns if the interval elapses, even if the object's state is nonsignaled. If dwMilliseconds is zero, the function tests the object's state and returns immediately. If dwMilliseconds is INFINITE, the function's time-out interval never elapses.

Re[4]: как проверить жив ли поток (TThread)
От: srid  
Дата: 30.05.06 07:52
Оценка:
Здравствуйте, ekamaloff, Вы писали:

E>
E>function CheckThreadIsAlive(Thread: TThread): Boolean;
E>begin
E>    Result := WaitForSingleObject(Thread.Handle, 0) = WAIT_OBJECT_0;
E>end;
E>


примерно так и сделал:
if (WAIT_TIMEOUT != WaitForSingleObject((HANDLE)(sec_thread->Handle), 1)) {
    /* thread "killed" */
};


но вот еще с одной деталью столкнулся:
как проверить, что поток не приостановлен из вне?
(приостановить можно через утилиту Process Explorer)
так не получается:
if (sec_thread->Suspended) { 
    /* сюда никогда не попадаем */ 
};


но следующая инструкция возобновляет работу потока в этом случае:
    sec_thread->Resume();
Re[5]: как проверить жив ли поток (TThread)
От: Danchik Украина  
Дата: 30.05.06 08:13
Оценка:
Здравствуйте, srid, Вы писали:

[Skip]

S>но вот еще с одной деталью столкнулся:

S>как проверить, что поток не приостановлен из вне?
S>(приостановить можно через утилиту Process Explorer)

[Skip]

Варианты:

1. Проверять GetThreadTimes — меняются ли они
2. Проводить тестовый suspend (выдрано из инета Hector Santos)
    BOOL IsThreadRunning(HANDLE  hThread) 
    { 
    DWORD dwCount; 


    // temporarily suspend thread to get 
    // previous suspend count 


    dwCount = SuspendThread(hThread); 


    // if no error, decrease the new suspend count 
    // by resuming the thread.  You must call 
    // ResumeThread if the above SuspendThread 
    // succeeded. 


    if (dwCount != 0xFFFFFFFF) ResumeThread(hThread); 


    // thread is running if suspend count was zero 


    return(dwCount==0); 
    }

3. Использовать Performance Counter — блин долго обьяснять
Re[5]: как проверить жив ли поток (TThread)
От: ekamaloff Великобритания  
Дата: 30.05.06 08:22
Оценка: 2 (1)
Здравствуйте, srid, Вы писали:

S>примерно так и сделал:

S>
S>if (WAIT_TIMEOUT != WaitForSingleObject((HANDLE)(sec_thread->Handle), 1)) {
S>    /* thread "killed" */
S>};
S>


Это совсем не то же самое, что предложил я, разве не видно?

S>но вот еще с одной деталью столкнулся:

S>как проверить, что поток не приостановлен из вне?
S>(приостановить можно через утилиту Process Explorer)

Честного способа нет. Можно попробовать порыть в сторону почти не документированной NtQueryInformationThread.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Re[6]: как проверить жив ли поток (TThread)
От: Danchik Украина  
Дата: 30.05.06 08:51
Оценка:
Здравствуйте, ekamaloff, Вы писали:

E>Здравствуйте, srid, Вы писали:


S>>примерно так и сделал:

S>>
S>>if (WAIT_TIMEOUT != WaitForSingleObject((HANDLE)(sec_thread->Handle), 1)) {
S>>    /* thread "killed" */
S>>};
S>>


E>Это совсем не то же самое, что предложил я, разве не видно?


Может вы и правы, для потоков WAIT_OBJECT_0 может быть и оно (туманный MSDN частенько), но, думаю, неплохо было бы тогда и WAIT_FAILED обрабатывать.
Re[7]: как проверить жив ли поток (TThread)
От: ekamaloff Великобритания  
Дата: 30.05.06 09:03
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Может вы и правы, для потоков WAIT_OBJECT_0 может быть и оно (туманный MSDN частенько), но, думаю, неплохо было бы тогда и WAIT_FAILED обрабатывать.


1 <> 0
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Re[8]: как проверить жив ли поток (TThread)
От: Danchik Украина  
Дата: 30.05.06 09:48
Оценка:
Здравствуйте, ekamaloff, Вы писали:

E>Здравствуйте, Danchik, Вы писали:


D>>Может вы и правы, для потоков WAIT_OBJECT_0 может быть и оно (туманный MSDN частенько), но, думаю, неплохо было бы тогда и WAIT_FAILED обрабатывать.


E>1 <> 0


Брр, Эльдар, обьясни мне такую штуку

WAIT_OBJECT_0 — значит поток активный? Я всегда считал что это значит что поток закончился Чесно не пробовал
Re[9]: как проверить жив ли поток (TThread)
От: ekamaloff Великобритания  
Дата: 30.05.06 10:03
Оценка:
Здравствуйте, Danchik, Вы писали:

E>>1 <> 0


D>Брр, Эльдар, обьясни мне такую штуку


D>WAIT_OBJECT_0 — значит поток активный? Я всегда считал что это значит что поток закончился Чесно не пробовал


В-общем под "1 <> 0" я имел ввиду то, что в приведенном мной коде период ожидания == 0, а не 1. Период ожидания, равный нулю, это особый режим работы WaitForSingleObject, при котором он просто проверяет состояние объекта синхронизации и немедленно возвращает управление. В этом смысле 0 совсем не равнозначен 1.

WaitForSingleObject

...
dwMilliseconds
[in] Time-out interval, in milliseconds. The function returns if the interval elapses, even if the object's state is nonsignaled. If dwMilliseconds is zero, the function tests the object's state and returns immediately. If dwMilliseconds is INFINITE, the function's time-out interval never elapses.


Если в случае с хендлом треда (равно как и с хендлом процесса) WaitForSingleObject возвращает WAIT_OBJECT_0, значит поток/процесс завершен. Я там кстати ошибку допустил, нужно было сравнивать не на равенство WAIT_OBJECT_0, а на равенство WAIT_TIMEOUT, видимо это вызвало у тебя вопрос. Приношу свои извинения если что
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Re[10]: как проверить жив ли поток (TThread)
От: Danchik Украина  
Дата: 30.05.06 10:09
Оценка: 1 (1)
Здравствуйте, ekamaloff, Вы писали:

[Skip]

E>Если в случае с хендлом треда (равно как и с хендлом процесса) WaitForSingleObject возвращает WAIT_OBJECT_0, значит поток/процесс завершен. Я там кстати ошибку допустил, нужно было сравнивать не на равенство WAIT_OBJECT_0, а на равенство WAIT_TIMEOUT, видимо это вызвало у тебя вопрос. Приношу свои извинения если что


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

Лана потом еще раз Рихтера полистаю, подзабылось...
Re[10]: как проверить жив ли поток (TThread)
От: srid  
Дата: 30.05.06 10:42
Оценка:
Здравствуйте, ekamaloff, Вы писали:

E>[skipped] Период ожидания, равный нулю, это особый режим работы WaitForSingleObject, при котором он просто проверяет состояние объекта синхронизации и немедленно возвращает управление. В этом смысле 0 совсем не равнозначен 1.

E>[skipped]
да, спасибо за замечание (imho, существенное)

E>Если в случае с хендлом треда (равно как и с хендлом процесса) WaitForSingleObject возвращает WAIT_OBJECT_0, значит поток/процесс завершен. Я там кстати ошибку допустил, нужно было сравнивать не на равенство WAIT_OBJECT_0, а на равенство WAIT_TIMEOUT, видимо это вызвало у тебя вопрос. Приношу свои извинения если что
Re: как проверить жив ли поток (TThread)
От: surovi  
Дата: 05.06.06 09:10
Оценка:
Здравствуйте, srid, Вы писали:
S>запущен поток на базе класса TThread
S>как проверить, существует(выполняется) ли он, или его кто-то грохнул?

Может CreateMutex поможет
Re: как проверить жив ли поток (TThread)
От: arist77  
Дата: 05.06.06 09:53
Оценка:
Здравствуйте, srid, Вы писали:

S>запущен поток на базе класса TThread


S>как проверить, существует(выполняется) ли он, или его кто-то грохнул?


Win32 API:
DWORD ec = 0; //exit code
if(!GetExitCodeThread(handle, &ec) || ec != STILL_ACTIVE)
//thread terminated
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.