多线程Thread类高级概念问题,高手进来(50分)

  • 主题发起人 主题发起人 sunstone
  • 开始时间 开始时间
S

sunstone

Unregistered / Unconfirmed
GUEST, unregistred user!
thread类中的handle和threadid两个属性有什么区别,都有什么具体用处?
我的个人理解:
handle是线程类的地址,threadid是系统给出的标识,不知道理解的对不对?但是threadid有什么具体用处呢?请高手讲一下概念
 
有些API函数需要threadid的
而且大多数全局的API函数都是用threadID的
 
那就是如果本进程内使用handle就足够了,用不着threadid标识
如果跨进程的应用,需要threadid
理解的对不对?
 
简单说,handle不能跨进程,而threadid是整个系统范围内唯一标识,可以跨进程使用。
 
不是的
handle也是可以在其它进程是得到的
不过它可能创建者所得到的Handle不一样
 
遇到这些问题时可以先看DELPHI HELP,觉得不够,可以看MSDN,网上搜。想要更深入了解
DELPHI是怎么包装的,就看DELPHI的源代码。
其实这个问题,DELPHI HELP已经很清楚了。
一:
Indicates the thread's handle (Windows only).
Delphi syntax:
property Handle: THandle;
C++ syntax:
__property int Handle = {read=FHandle, nodefault};
Description
On Windows, use Handle for calling Win32 API functions for thread manipulation.
The Handle property is not available on Linux.
handle就是线程的句柄。
二:
Identifies the thread throughout the system.
Delphi syntax:
On Windows:
property ThreadID: THandle;
On Linux:
property ThreadID: Cardinal;
C++ syntax:
On Windows:
__property int ThreadID = {read=FThreadID, nodefault};
On Linux:
__property unsigned int ThreadID = {read=FThreadID, nodefault};
Description
Use ThreadID, during debugging, to identify the thread in the Threads status box. On Windows, ThreadID is also useful when calling Win32 API functions for manipulating the thread.
Note: ThreadID is different than the thread抯 handle in the Handle property.
为了更加搞清楚ThreadID到底有什么用,我再查看一下DELPHI的TThread,
FHandle := begin
Thread(nil, 0, @ThreadProc, Pointer(Self), CREATE_SUSPENDED, FThreadID);
再跟进到system
function begin
Thread(SecurityAttributes: Pointer;
StackSize: LongWord;
ThreadFunc: TThreadFunc;
Parameter: Pointer;
CreationFlags: LongWord;
var ThreadId: LongWord): Integer;
var
P: PThreadRec;
begin
New(P);
P.Func := ThreadFunc;
P.Parameter := Parameter;
IsMultiThread := TRUE;
Result := CreateThread(SecurityAttributes, StackSize, @ThreadWrapper, P,
CreationFlags, ThreadID);
end;
这里的ThreadID带了VAR其实就是一个指针
再查MSDN
CreateThread
The CreateThread function creates a thread to execute within the virtual address space of the calling process.
To create a thread that runs in the virtual address space of another process, use the CreateRemoteThread function.

HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
Parameters
lpThreadAttributes
[in] Pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If lpThreadAttributes is NULL, the handle cannot be inherited.
The lpSecurityDescriptor member of the structure specifies a security descriptor for the new thread. If lpThreadAttributes is NULL, the thread gets a default security descriptor. The ACLs in the default security descriptor for a thread come from the primary token of the creator.
Windows XP/2000/NT: The ACLs in the default security descriptor for a thread come from the primary or impersonation token of the creator. This behavior changed with Windows XP SP2 and Windows Server 2003.
dwStackSize
[in] Initial size of the stack, in bytes. The system rounds this value to the nearest page. If this parameter is zero, the new thread uses the default size for the executable. For more information, see Thread Stack Size.
lpStartAddress
[in] Pointer to the application-defined function to be executed by the thread and represents the starting address of the thread. For more information on the thread function, see ThreadProc.
lpParameter
[in] Pointer to a variable to be passed to the thread.
dwCreationFlags
[in] Flags that control the creation of the thread. If the CREATE_SUSPENDED flag is specified, the thread is created in a suspended state, and will not run until the ResumeThread function is called. If this value is zero, the thread runs immediately after creation.
If the STACK_SIZE_PARAM_IS_A_RESERVATION flag is specified, the dwStackSize parameter specifies the initial reserve size of the stack. Otherwise, dwStackSize specifies the commit size.
Windows 2000/NT and Windows Me/98/95: The STACK_SIZE_PARAM_IS_A_RESERVATION flag is not supported.
lpThreadId
[out] Pointer to a variable that receives the thread identifier. If this parameter is NULL, the thread identifier is not returned.
Windows Me/98/95: This parameter may not be NULL.
到这里应该清楚了,
这个参数用来接收线程的标识号的。NULL指示不需要返回值,而在ME、98、95这个参数可能不能为NULL。
在TThread中,使用了要求返回值,并放在TThreadID中。这样就可以兼容ME 98....了。
那DEPHI用这个FThreadID到底有什么作用呢?
destructor TThread.Destroy;
begin
if (FThreadID <> 0) and not FFinished then
begin
Terminate;
if FCreateSuspended then
Resume;
WaitFor;
end;
{$IFDEF MSWINDOWS}
if FHandle <> 0 then
CloseHandle(FHandle);
{$ENDIF}
代码我就不解释了。到这里应该非常明白了。
 
windows api 手册关于createthread 函数这样解释threadid:指向一个32位值,他接受改成成的标识符。winnt中,若该参数为null,则不返回该线程标识符;win95/98中,该参数不能为null
为什么delphi的destructor TThread.Destroy;中使用threadid,而不是用handle来判断
能否这样:
destructor TThread.Destroy;
begin
if (FHandle<> 0) and not FFinished then
//Fthreadid 改成FHandle
begin
Terminate;
if FCreateSuspended then
Resume;
WaitFor;
end;
{$IFDEF MSWINDOWS}
if FHandle <> 0 then
CloseHandle(FHandle);
{$ENDIF}
 
都查到这里了楼主还不明白??
这些代码是要跨平台的,而在Linux下面没有Handle
 
是的,D7的代码中,有些东西也是需要为跨平台考虑,
这里的//Fthreadid 改成FHandle在MS下没问题的。但LINUX下就不行。可以看create方法。
 
多人接受答案了。
 
后退
顶部