进行中所有的线程都可以使用ExitThread函数来退出.退出的时候,堆栈都被释放,所有引用改点的句柄都会受到信号.(如果线程链接到了一个或多个DLL,那么系统将会使用DLL_THREAD_DETACH来调用每个DLL的DLLMain函数
当线程中的最后一个线程退出,进程本身也就终止了.
一个线程可使用TerminateThread函数来终止另一个线程,但该线程的资源就不会释放,而且不会通知已经附加的Dll.故不推荐使用
已终止的线程(注意,线程应该自己终止) 会继续存在,直到最后一个引用它的句柄通过CloseHandle关闭,其他线程(见下).可取出GetExitCodeThread取出退出码,如果线程还在运行,则这个值是STILL_ACTIVE
BOOL WINAPI GetExitCodeThread(
_ In_ HANDLE hThread,
_ Out_ LPDWORD lpExitCode
);
hThread必须有THREAD_QUERY_INFORMATION 或者 THREAD_QUERY_LIMITED_INFORMATION 访问权限(XP:必须有THREAD_QUERY_INFORMATION 访问权限)
这个函数是立即返回的,如果线程并未终止而且函数成功了,返回值是STILL_ACTIVE,如果线程终止而且函数成功,那么返回值是以下:
{
}
可以通过以下函数来获取线程ID和句柄
{
}
更多的线程管理函数:
GetProcessIdOfThread,这个函数不支持XP,它从线程的句柄中找出进程ID!,在管理与其他进程的线程交互时可使用这个函数,当然,也可使用OpenProcess来获取进程句柄
GetThreadIOPendingFlags,确定句柄所标示的线程是否有尚未完成的I/O请求
每个线程都有一个挂起计数,只有在计数为0时线程才会执行,一个线程可以通过使用SuspendThread和ResumeThread来递增或递减另外一个线程的挂起计数,这两个函数成功时都返回上一个挂起计数值,(DWORD)(-1)表示失败
等待线程终止,值得表演的一点的是,Windows在这里高度统一,等待函数只有两个(WaitForSingleObject和WaitForMultipleObjects).在等待多个句柄时,他们可以是不同类型的句柄,如线程,进程或其他的类型都可以在一个调用中混用
WaitForMultiplesObjects一次只能等待MAXIMUM_WAIT_OBJECTS个句柄,等待函数等候有句柄所表示的对线变成已传信状态.(ExitThread和TerminateThread会设置线程为已传信状态).一旦线程已传信,那么它永远不会再变成未传信状态
在许多操作系统中,线程是一个很盛名的概念,许多UNIX供应商和用户都提供了他们自己转有的实现,有些线程库是在内核外部实现.POSIX线程现在是标准,.Pthread是所有商用UNIX和Linux实现的一部分.pthread_chreate等教育CreateThread,pthread_exit等价于ExitThread,一个线程使用pthread_join来等待一个线程退出.当然还有强大的pthrad_cancel函数,它与TerminateThread不同,他确保处理程序和取消处理程序能够得到执行
在线程中使用C库,但是C库是为在单一线程的进程中编写的.有些函数使用全局存储来存储中间结果,这样的库不是线程安全的比如strok,当然,MS提供了个LIBCMT.lib线程安全的C库,但是搞笑的是,你不能再使用CreateThread,你需要使用_beginthread(ex)创建线程和_endthread来终结(不被推荐,不运行传入返回值),最搞笑的是,你可以把这个函数返回的值转成HANDLE类型然后去交给WINAPI使用!!!!真是让人啼笑是非
程序例子,并行搜索:
for (iThrd = 0; iThrd < argc - 2; iThrd++) {
/* Set: targv[1] to the pattern
targv[2] to the input file
targv[3] to the output file. */
_tcscpy(gArg[iThrd].targv[1], argv[1]); /* Pattern. */
_tcscpy(gArg[iThrd].targv[2], argv[iThrd + 2]); /* Search file. */
if (GetTempFileName /* Temp file name */
(TEXT("."), TEXT("Gre"), 0, gArg[iThrd].targv[3]) == 0)
return;
/* Output file. */
gArg[iThrd].argc = 4;
/* Create a thread to execute the command line. */
tHandle[iThrd] = (HANDLE)_beginthreadex(
NULL, 0, ThGrep, &gArg[iThrd], 0, NULL);
if (tHandle[iThrd] == 0)
return;
}
/* Threads are all running. Wait for them to complete
one at a time and put out the results. */
/* Redirect output for "cat" process listing results. */
startUp.dwFlags = STARTF_USESTDHANDLES;
startUp.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
startUp.hStdError = GetStdHandle(STD_ERROR_HANDLE);
threadCount = argc - 2;
while (threadCount > 0) {
threadIndex = WaitForMultipleObjects(threadCount, tHandle, FALSE, INFINITE);
iThrd = (int)threadIndex - (int)WAIT_OBJECT_0;
if (iThrd < 0 || iThrd >= threadCount)
return;
GetExitCodeThread(tHandle[iThrd], &exitCode);
CloseHandle(tHandle[iThrd]);
/* List file contents (if a pattern match was found)
and wait for the next thread to terminate. */
if (exitCode == 0) {
if (argc > 3) { /* Print file name if more than one. */
_tprintf(_T("%s\n"),
gArg[iThrd].targv[2]);
fflush(stdout);
}
_stprintf(commandLine, _T("cat \"%s\""), gArg[iThrd].targv[3]);
ok = CreateProcess(NULL, commandLine, NULL, NULL,
TRUE, 0, NULL, NULL, &startUp, &processInfo);
if (!ok) return;
WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
if (!DeleteFile(gArg[iThrd].targv[3]))
return;
/* Move the handle of the last thread in the list
to the slot occupied by thread that just completed
and decrement the thread count. Do the same for
the temp file names. */
tHandle[iThrd] = tHandle[threadCount - 1];
_tcscpy(gArg[iThrd].targv[3], gArg[threadCount - 1].targv[3]);
_tcscpy(gArg[iThrd].targv[2], gArg[threadCount - 1].targv[2]);
threadCount--;
}