HANDLE WINAPI CreateThread ( __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, // 指向SECURITY_ATTRIBUTES 的指针,为新线程指定安全描述 __in SIZE_T dwStackSize, // 初始化线程堆栈尺寸 __in LPTHREAD_START_ROUTINE lpStartAddress, //线程函数所指向的地址起始函数 __in_opt LPVOID lpParameter, // 给线程函数传递的参数 __in DWORD dwCreationFlags, // 有关线程的标志 __out_opt LPDWORD lpThreadId //系统分配给线程的ID );
----第一个参数是安全属性,通常设为null,使用缺省的安全属性。当咱们想此线程有另外的子进程时,可改变它的属性。
----第二个参数是线程堆栈尺寸,通常设为0,表示与此应用的堆栈尺寸相同,即主线程与建立的线程同样长度的堆栈。而且其长度会根据须要自动变长。
----第三个参数,也是最重要的一个,是一个指向函数名的指针,或者函数名字
----第四个参数是你须要向线程函数传递的参数,通常是一个指向结构的指针。不需传递参数时,则这个参数设为null。
----第五个参数,传入与线程有关的一些标志,若是是CREATE_SUSPENDED,则建立一个挂起的线程,即这个线程自己已建立,它的堆栈也已建立。但这个线程不会被分配给CPU时间,只有当ResumeThread函数被调用后才能执行;固然,也能够调用SuspendThread函数再次挂起线程。要是标志为0,那么一旦创建线程,线程函数就被当即调用。通常传为0便可。 ----第六个参数是系统分配给这个线程的惟一的ID标志 windows
// MultiTread2.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <windows.h> #include <stdio.h> #define MAX_THREADS 10 typedef struct MyData { int val1; int val2; //char key[32]; }MYDATA; DWORD WINAPI ThreadProc(LPVOID lpParam) { MYDATA *pmd = (MYDATA *)lpParam; printf("%d\n", pmd->val1); printf("%d\n", pmd->val2); return 0; } DWORD(WINAPI *pThreadProc)(LPVOID lpParam); void fun() { pThreadProc = ThreadProc; MYDATA mydt[MAX_THREADS]; HANDLE hThread[MAX_THREADS]; int i; for (i = 0; i < MAX_THREADS; i++) { mydt[i].val1 = i; mydt[i].val2 = i + 1; hThread[i] = CreateThread( NULL,// default security attributes 0,// use default stack size pThreadProc,// thread function &mydt[i],// argument to thread function 0, // use default creation flags NULL); if (hThread[i] == NULL) { ExitProcess(i); } } // Wait until all threads have terminated. WaitForMultipleObjects(MAX_THREADS, hThread, TRUE, INFINITE); //这样传给回调函数的参数不用定位static或者new出来的了 // Close all thread handles upon completion. for (i = 0; i < MAX_THREADS; i++) { CloseHandle(hThread[i]); } } int _tmain(int argc, _TCHAR* argv[]) { fun(); getchar(); return 0; }
注意:传给函数的参数,要保证当运行回调函数时候,参数不能被销毁。数组
好比这里参数是局部变量栈。安全
若是将 ide
WaitForMultipleObjects(MAX_THREADS, hThread, TRUE, INFINITE); //这样传给回调函数的参数不用定位static或者new出来的了
屏蔽,
那么传递给回调函数的参数就可能已经被销毁,调用函数的时候就会出错、
除非将传入的参数定义为static 或者其余在调用完全部线程前不被销毁的变量
DWORD WaitForMultipleObjects( DWORD dwCount, CONST HANDLE* phObjects, BOOL fWaitAll, DWORD dwMilliseconds );
说明这一状况的一些示例代码: HANDLE h[3]; h[0] = hProcess1; h[1] = hProcess2; h[2] = hProcess3; DWORD dw = WaitForMultipleObjects(3, h, FALSE, 5000); switch(dw) { case WAIT_FAILED: // Bad call to function (invalid handle?) break; case WAIT_TIMEOUT: // None of the objects became signaled within 5000 milliseconds. break; case WAIT_OBJECT_0 + 0: // The process identified by h[0] (hProcess1) terminated. break; case WAIT_OBJECT_0 + 1: // The process identified by h[1] (hProcess2) terminated. break; case WAIT_OBJECT_0 + 2: // The process identified by h[2] (hProcess3) terminated. break; }
若是为fWaitAll参数传递 FALSE,WaitForMultipleObjects就从索引0开始向上对句柄数组进行扫描,同时已通知的第一个对象终止等待状态。函数
这可能产生一些 你不但愿有的结果。spa
例如,经过将3个进程句柄传递给该函数,你的线程就会等待3个子进程终止运行。若是数组中索引为0的进程终止运 行,WaitForMultipleObjects就会返回。这时该线程就能够作它须要的任何事情,而后循环反复,等待另外一个进程终止运行。线程
若是该线程传 递相同的3个句柄,该函数当即再次返回WAIT_OBJECT_0。除非删除已经收到通知的句柄,不然代码就没法正确地运行指针