Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.190.152.38] |
|
Сообщ.
#1
,
|
|
|
Скажите, пожалуйста, можно ли:
1) узнать по Handle существует ли в системе поток с этим Handle 2) узнать текущее состояние потока(suspended или resume) по его Handle с помощью API-функции. |
Сообщ.
#2
,
|
|
|
Цитата DelphiLexx @ 1) узнать по Handle существует ли в системе поток с этим Handle function GetExitCodeThread(hThread: THandle; var lpExitCode: DWORD): BOOL; stdcall; Добавлено Цитата DelphiLexx @ 2) узнать текущее состояние потока(suspended или resume) по его Handle с помощью API-функции. Вот оддельной Апишки я не видел но можно хитрым способом узнавать: function StatThread(HT:Thandle):boolean; var i:integer; bagin i:=suspendthread(HT); if i=-1 then begin result:=false; exit; end; resumethread(HT); if i=0 then result:=true else result:=false; end; если поток не существует или он на паузе тогда возвратится лож если он запущен тогда истину. пс. все дело втом что когда с помощю функции suspendthread перевести поток в паузу то возврящается ноль если несколько раз так повторить то число увеличивается, получается что если поток стоит на паузе тогда возврат будет 1 если он выполняется тогда будет 0. но нужно не забыть вернут прежнее состояние если мы дважди поствили его на паузу то прийдется дважди ее снимать для запуска. |
Сообщ.
#3
,
|
|
|
А вот здесь
Цитата ViktorXP @ end; resumethread(HT); if i=0 then result:=true else result:=false; случайно не так: Цитата ViktorXP @ end; I := resumethread(HT); if i=0 then result:=true else result:=false; Добавлено Цитата ViktorXP @ i:=suspendthread(HT); И suspendthread не может вернуть -1 т.к. у него возвращаемый тип dword |
Сообщ.
#4
,
|
|
|
DelphiLexx нет я ничего не перепутал.
Цитата DelphiLexx @ И suspendthread не может вернуть -1 т.к. у него возвращаемый тип dword просто при ошибки он возвращает максимальное число а теперь отними от нуля 1 что получится Добавлено Цитата If the function succeeds, the return value is the thread's previous suspend count; otherwise, it is (DWORD) -1. To get extended error information, use the GetLastError function. Добавлено хотя i нужно было объявить не как integer а ка DWORD |
Сообщ.
#5
,
|
|
|
1. ИМХО, наиболее универсальный метод с помощью Native API (используются заголовки JEDI API - http://jedi-apilib.sourceforge.net/ ):
uses JwaNative, JwaNtStatus; // Упрощенно, без проверок на ошибки function GetObjectTypeName(Handle: THandle): String; var Info: Pointer; BasicInfo: _OBJECT_BASIC_INFORMATION; Size: Cardinal; begin NtQueryObject(Handle,ObjectBasicInformation,@BasicInfo,SizeOf(_OBJECT_BASIC_INFORMATION),nil); GetMem(Info,BasicInfo.TypeInformationLength); try if NtQueryObject(Handle,ObjectTypeInformation,Info,BasicInfo.TypeInformationLength,@Size) = STATUS_INFO_LENGTH_MISMATCH then begin; ReallocMem(Info,Size); NtQueryObject(Handle,ObjectTypeInformation,Info,Size,nil); end; Result:=WideCharToString(POBJECT_TYPE_INFORMATION(Info)^.Name.Buffer); finally FreeMem(Info); end; end; function IsThread(Handle: THandle): Boolean; begin Result:=GetObjectTypeName(Handle) = 'Thread'; end; 2. Есть у меня идейка тоже как это сделать, но что-то уж очень там наворочено, я лучше сначала проверю, если получится - отпишусь. |
Сообщ.
#6
,
|
|
|
Rose я канешно ничего не имею против других вариантов только зачем заменять одну апишку кучей кода
я бы ничего не говорл если тамбы была всего одна большая процедура но цепляются еще два модуля но это только мое мнение и не все могут с ним согласится |
Сообщ.
#7
,
|
|
|
ViktorXP
Это универсальный метод. Позволяет по дескриптору узнать тип объекта вообще, а не проверить только на Thread. Если понадобится проверить на Process, File, Event, Port и т.д. - тот же самый код А насчет лишних модулей - так это же всего лишь заголовочные файлы с описанием типов и импортируемых функций. Как Windows.pas, к тому же, не такие уж и экзотичные... JEDI API достаточно популярная вещь. К тому же, десяток строчек - это куча кода?.. |
Сообщ.
#8
,
|
|
|
Цитата Rose @ Это универсальный метод. Ну раз он много чего может тогда даю добро на его существование Цитата Rose @ JEDI API достаточно популярная вещь. Слышал но ни когда не пользовался. В моих разработках очень мало сторонего. Цитата Rose @ К тому же, десяток строчек - это куча кода?.. Если со стороны отладки: чем больше кода тем труднее в нем разобратся. А если учесть что это еще и не твое ... |
Сообщ.
#9
,
|
|
|
Цитата В моих разработках очень мало сторонего. Хм Как сказать... Даже стандартные юниты не используете? JEDI API - это затыкание сообществом дыр со стороны Borland. Как известно, импорт далеко не всех АПИ (даже тех, которые нужны повседневно) в стандартных дельфийских юнитах содержаться, а в JEDI с этим куда лучше. Недавно, когда Джим Дуглас (генеральный директор CodeGear) в Россию приезжал, этот вопрос поднимался. Считаю, что такие задачи они должны решать сами, а не полагаться на сообщество. ИМХО. |
Сообщ.
#10
,
|
|
|
Да действительно в борланд не все апишки включены. А к JEDI API хорошая докомунтация есть?
Обязательно как нить попробую. Добавлено Цитата Rose @ Даже стандартные юниты не используете? я имею ввиду под стороними - все то что от стороних разработчиков |
Сообщ.
#11
,
|
|
|
Цитата А к JEDI API хорошая докомунтация есть? Есть! В MSDN Где и положено быть документации по WinAPI. Юниты из JEDI API - это грубо говоря большое расширение к Windows.pas. Разумеется, NativeAPI из моего примера недокументированы... |
Сообщ.
#12
,
|
|
|
Ну тогда это понижает шансы использовать ее в моих проэктах. С таким успехом я и сам могу модуль писнуть.
И сразу опережаю. Согласен с утверждением: "Зачем писать если уже готовое есть" . Но в нем еще нужно будет разобратся а если для ее разбора нужна будет MSDN.... зачем мне эти модули если я всеравно буду изучать MSDN. пс. тут решает каждый для себя сам что ему легче. |
Сообщ.
#13
,
|
|
|
А разве я настаиваю - хозяин-барин Хотя аргументация мне нравится, получается, что если бы документация была, вы бы ее не изучали, так как
Цитата в нем еще нужно будет разобратся Windows.pas вы по этой же причине не используете? Сами импортируете? Лично мне использование этого сэкономило массу времени, так как ручками описывать все стандартные типы и импортировать функции - задача весьма утомительная... |
Сообщ.
#14
,
|
|
|
В общем, как и обещал, реализация второго пункта без Resume/Suspend, а прямо на лету На этот раз даже с проверками на ошибки. "Полезные" здесь функции IsThreadSuspended и GetThreadIdByHandle, остальные - просто рабочие.
uses SysConst, JwaNative, JwaWinType, JwaNtStatus; function NtErrorMessage(Code: NTSTATUS): String; var hMod: Cardinal; Buffer: array[0..255] of Char; Len: Integer; begin hMod:=GetModuleHandle(ntdll); Len := FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_IGNORE_INSERTS or FORMAT_MESSAGE_ARGUMENT_ARRAY or FORMAT_MESSAGE_FROM_HMODULE, Pointer(hMod), Code, 0, Buffer, SizeOf(Buffer), nil); while (Len > 0) and (Buffer[Len - 1] in [#0..#32, '.']) do Dec(Len); SetString(Result, Buffer, Len); end; function NtSuccess(Code: NTSTATUS): Boolean; begin Result:=Code >= 0; end; procedure NtCheck(Code: NTSTATUS); begin if not NtSuccess(Code) then begin raise EOSError.CreateResFmt(@SOSError, [Code,NtErrorMessage(Code)]); end; end; function GetSystemInfoTable(ASystemInformationClass: SYSTEM_INFORMATION_CLASS; out Info: Pointer; out Size: Cardinal): NTSTATUS; var SystemInfo: TSystemInfo; ReturnSize: Cardinal; ContinueFlag: Boolean; begin GetSystemInfo(SystemInfo); Size:=SystemInfo.dwPageSize; repeat Info:=VirtualAlloc(nil,Size,MEM_COMMIT or MEM_RESERVE,PAGE_READWRITE); if Info = nil then RaiseLastOSError; Result:=NtQuerySystemInformation(ASystemInformationClass,Info,Size,@ReturnSize); ContinueFlag:=Result = STATUS_INFO_LENGTH_MISMATCH; if ContinueFlag then begin Win32Check(VirtualFree(Info,0,MEM_RELEASE)); if ReturnSize = 0 then Size:=Size + SystemInfo.dwPageSize else Size:=ReturnSize; end; until not ContinueFlag; end; function GetThreadIdByHandle(Handle: THandle): Cardinal; var Info: _THREAD_BASIC_INFORMATION; begin NtCheck(NtQueryInformationThread(Handle,ThreadBasicInformation,@Info, SizeOf(_THREAD_BASIC_INFORMATION),nil)); Result:=Info.ClientId.UniqueThread; end; function IsThreadSuspended(ThreadID: Cardinal): Boolean; var Info, Entry: Pointer; Size, i: Cardinal; ContinueFlag: Boolean; begin Result:=false; NtCheck(GetSystemInfoTable(SystemProcessesAndThreadsInformation,Info,Size)); try Entry:=Info; ContinueFlag:=true; while ContinueFlag do begin for i:=0 to PSYSTEM_PROCESSES(Entry)^.ThreadCount - 1 do begin if PSYSTEM_PROCESSES(Entry)^.Threads[i].ClientId.UniqueThread = ThreadID then begin Result:=PSYSTEM_PROCESSES(Entry)^.Threads[i].WaitReason = Suspended; ContinueFlag:=false; Break; end; end; if (PSYSTEM_PROCESSES(Entry)^.NextEntryDelta <> 0) then Cardinal(Entry):=Cardinal(Entry) + PSYSTEM_PROCESSES(Entry)^.NextEntryDelta else ContinueFlag:=false; end; finally VirtualFree(Info,0,MEM_RELEASE); end; end; |