Posted on 2010-02-22 11:15
sin 阅读(4107)
评论(2) 编辑 收藏 引用 所属分类:
WIN32编程
Win32中,内核对象属于WINDOWS的,而不属于进程。进程对象、线程对象、文件对象、文件映射对象、事件对象、互斥量对象等都属于内核对象。WIN32中一般通过CreateXXXX来创建内核对象,返回一个内核对象的句柄,进程不能直接操作内核对象,只能通过该句柄来访问内核对象。内核对象有一个使用计数,一个进程的内核对象句柄表中引用了某个内核对象,该内核对象的使用计数就递增1,该进程调用CloseHandle时,引用计数递减,当引用计数为0时,内核对象被销毁,当进程退出时,进程所引用内核对象的引用计数都递减1。
线程也是内核对象,当创建一个线程时,默认引用计数是2。调用CloseHandle时,线程引用计数下降1;当线程结束时,引用计数再下降1。仅仅调用CloseHandle并不能保证线程结束。利用这个特点,我们可以在调用CloseHandle前用GetExitCodeThread获得线程的结束代码,如果线程是STILL_ACTIVE状态,表示线程尚未结束。下面是一个能保证线程正常结束例子:
不过例子中等待线程结束的方法非常笨,用一个for循环不断检测线程状态,如果两个线程都结束了,才跳出循环,更好的方法是WaitForSigleObject,后面介绍。
1 /*
2 * ExitCode.c
3 *
4 * Sample code for "Multithreading Applications in Win32"
5 * This is from Chapter 2, Listing 2-2
6 *
7 * Start two threads and try to exit
8 * when the user presses a key.
9 */
10
11 #define WIN32_LEAN_AND_MEAN
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <windows.h>
15 #include <conio.h>
16
17 DWORD WINAPI ThreadFunc(LPVOID);
18
19 int main()
20 {
21 HANDLE hThrd1;
22 HANDLE hThrd2;
23 DWORD exitCode1 = 0;
24 DWORD exitCode2 = 0;
25 DWORD threadId;
26
27 hThrd1 = CreateThread(NULL,
28 0,
29 ThreadFunc,
30 (LPVOID)1,
31 0,
32 &threadId );
33 if (hThrd1)
34 printf("Thread 1 launched\n");
35
36 hThrd2 = CreateThread(NULL,
37 0,
38 ThreadFunc,
39 (LPVOID)2,
40 0,
41 &threadId );
42 if (hThrd2)
43 printf("Thread 2 launched\n");
44
45
46 // Keep waiting until both calls to
47 // GetExitCodeThread succeed AND
48 // neither of them returns STILL_ACTIVE.
49 // This method is not optimal - we'll
50 // see the correct way in Chapter 3.
51 for (;;)
52 {
53 printf("Press any key to exit..\n");
54 getch();
55
56 GetExitCodeThread(hThrd1, &exitCode1);
57 GetExitCodeThread(hThrd2, &exitCode2);
58 if ( exitCode1 == STILL_ACTIVE )
59 puts("Thread 1 is still running!");
60 if ( exitCode2 == STILL_ACTIVE )
61 puts("Thread 2 is still running!");
62 if ( exitCode1 != STILL_ACTIVE
63 && exitCode2 != STILL_ACTIVE )
64 break;
65 }
66
67 CloseHandle(hThrd1);
68 CloseHandle(hThrd2);
69
70 printf("Thread 1 returned %d\n", exitCode1);
71 printf("Thread 2 returned %d\n", exitCode2);
72
73 return EXIT_SUCCESS;
74 }
75
76
77 /*
78 * Take the startup value, do some simple math on it,
79 * and return the calculated value.
80 */
81 DWORD WINAPI ThreadFunc(LPVOID n)
82 {
83 Sleep((DWORD)n*1000*2);
84 return (DWORD)n * 10;
85 }
线程也可以自己结束掉自己,方法是调用ExitThread。尽量不在主线程中调用ExitTread,这样会强制其他线程终止,进程终止,而其他线程没有机会做清理工作。