CreateProcess还会为进程和线程分配一个ID号。进程和线程分享同一个号码池。这意味着它们不可能相同。一个对象的ID不可能分配到0,因为windows任务管理器将进程ID 0与系统空闲进程关联。该进程代表未被真实使用的cpu使用率。

  dwProcessId和dwThreadId成员是存储进程和线程的ID。使用GetCurrentProcessId可以获得当前进程的ID。GetCurrentThreadId来获得当前正在运行的线程的ID。另外使用GetProcessId和GetThreadId可以获得指定句柄对应的进程和线程的ID。使用GetProcessIDOfThread可以获得某句柄关联的线程所在进程的ID。

  由于ID可能会立即重用。也是说当我们获得某个进程的ID并保存后,此后在使用时有可能出现它已经被释放了。此时此ID对应着其他进程了。避免这种情况的方法是:保证进程或线程对象不被销毁。

  进程终止

  进程可以通过三种方式终止:

  1:主线程从入口函数返回。

  2:进程中的一个线程调用ExitProcess。

  3:另一个进程中的线程调用TerminateProcess。

  在以上介绍的三种方式中仅有第一种,当主线程从入口函数返回才保证主线程的所有资源都会被正确清理。

  清理操作包括:

  1:调用所有在本进程内使用的任何C++对象的析构函数。

  2:释放各个线程线程栈使用的内存。

  3:进程的退出代码被设为入口函数的返回值。

  4:进程内核对象使用计数递减1。

  正常情况下入口点函数会返回到启动函数,启动函数将正确清理进程使用的所有C运行时资源,清理之后启动代码显式调用ExitProcess并将入口函数返回值传给它。这也是为什么只需从入口函数返回却可以终止整个进程的原因。

  进程的一个线程调用ExitProcess可以终止本进程。其后的别的代码将不会被执行。

  与ExitProcess相类似的还有ExitThread,它会导致一个线程终止。在创建线程时常出现这种情况:子线程还没有怎么执行程序已经结束了,这有可能是在创建完线程后,主线程没有调用WaitForSingleObject之类的函数,主线程创建完其他线程后返回到启动函数函数返回整个进程被终止。这一点很容易出错。

  调用ExitProcess或是ExitThread会导致进程或线程当场终止运行,再也不会返回到启动函数,清理工作(C++对象的析构)当然没法执行。虽然终随着进程的结束,该进程内所有线程所使用的资源都会被释放,但是应该避免调用这些函数,它们阻止了C++对象析构函数对善后工作的处理。顺便提下,如果在主线程调用ExitThread,虽然主线程当场终止,但是如果进程内还有其他线程,则进程不会终止。

  如以下代码:


#include<windows.h>

#include<iostream>

DWORD ThreadProc(PVOID)

{

 int i=0;

 int j=0;

while(i<1000000)

 {

 i++;

 while(j<10000)

  j++;

 std::cout<<i<<","<<j<<std::endl;

 }

 return 0;

}

int main(int argc,char**argv)

{

 DWORD id;

 CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadProc,NULL,0,&id);

 ExitThread(0);

 return 0;

}