Summary:
总结Win32提供的创建多线程相关的API接口和基本的使用框架。
Ref:
MSDN: http://msdn.microsoft.com/zh-cn/library/y6h8hye8(v=VS.100)
Win32多线程的创建方法主要有:
(1)CreateThread()
(2)_beginthread()&&_beginthreadex()
(3)AfxBeginThread()
(4)CWinThread类
(1)CreateThread()
百度百科:http://baike.baidu.com/view/1191444.htm
函数原型:
HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); }
头文件:Windows.h
CreateThread是Win32提供的创建线程的最基础的API,用于在主线程上创建一个线程。返回一个HANDLE句柄(内核对象)。
参数简要说明:
lpThreadAttributes:线程属性,用于设置线程的属性,NULL表示使用默认的设置。dwStackSize:线程堆栈大小,使用0采用默认设置,windows会根据需要动态增加堆栈大小。lpStartAddress:指向线程函数的指针。lpParameter:向线程函数传递的参数。dwCreationFlags:线程标志,CREATE_SUSPENDED表示创建一个挂起的线程,0表示创建后立即激活线程。lpThreadId,先线程的ID(输出参数)。
创建线程的代码:
#include "stdafx.h" #include <Windows.h> DWORD WINAPI ThreadProc(LPVOID lpParam) { printf("sub thread started\n"); printf("sub thread finished\n"); return 0; } int main(int argc, char* argv[]) { DWORD threadID; HANDLE hThread; hThread = CreateThread(NULL,0,ThreadProc,NULL,0,&threadID); // 创建线程 return 0; }
如果直接使用上面的代码,那么很可能没有任何输出,这是由于主线程创建了子线程后主线程继续向下运行,子线程还没来得及执行里面的代码主线程可能就结束了。这就需要另一个API来进行同步:WaitForSingleObject()。
与之对应的还有WaitForMultipleObjects,用于同步一组内核对象。(参考http://msdn.microsoft.com/zh-cn/site/ms686360获取所有的同步函数(Synchronization Functions)的使用。
WaitForSingleObject原型:DWORD WINAPI WaitForSingleObject(__in HANDLE hHandle, __in DWORD dwMilliseconds);其中,第一个参数是要等待的内核对象的句柄,第二个参数是设置等待超时时间,可以设置为INFINITE,表示一直等待直到有信号触发。
在内核对象使用完毕后,一般需要关闭,使用CloseHandle()函数,参数为内核对象句柄。
所以,以下是一个最基本的使用CreateThread的例子:
#include "stdafx.h" #include <Windows.h> DWORD WINAPI ThreadProc(LPVOID lpParam) { printf("sub thread started\n"); // TODO: Add your thread code here. printf("sub thread finished\n"); return 0; } int main(int argc, char* argv[]) { DWORD threadID; HANDLE hThread; hThread = CreateThread(NULL,0,ThreadProc,NULL,0,&threadID); // 创建线程 WaitForSingleObject(hThread,INFINITE); CloseHandle(hThread); // 关闭内核对象 return 0; }
百度百科:http://baike.baidu.com/view/3029167.htm
MSDN:http://msdn.microsoft.com/zh-cn/library/kdzttdcb.aspx
函数原型:
uintptr_t _beginthread( // NATIVE CODE void( __cdecl *start_address )( void * ), unsigned stack_size, void *arglist );
头文件:process.h
参数说明:第一个参数是线程函数的指针,第二个参数是堆栈大小,第三个参数是要传递给线程函数的参数列表。返回值也是线程句柄(关于更多说明,参考MSDN)。同样,对于_beginthread()的同步,和CreateThread一样可以使用WaitForSingleObject函数,CloseHandle()关闭内核对象。另外,_beginthread()的线程函数是无返回值类型的,可以使用_endthread()在线程函数中结束线程。
下面是一个使用_beginthread()的基本的例子:
#include "stdafx.h" #include <Windows.h> #include <process.h> void __cdecl ThreadProc(void *para) { printf("sub thread started\n"); // TODO: Add your thread code here. printf("sub thread finished\n"); _endthread(); // 可以省略,隐含会调用。 } int main(int argc, char* argv[]) { HANDLE hThread = (HANDLE)_beginthread(ThreadProc, 0, NULL); WaitForSingleObject(hThread,INFINITE); CloseHandle(hThread); }另外,还有一个函数_beginthreadex(),可以简单的认为_beginthread()为其简化版,所以更多的时候是使用更简单的_beginthread()了。
问题引出:CreateThread的内存泄漏问题(CreateThread和_beginthread的区别)
Related Topics:http://wenku.baidu.com/view/adede4ec4afe04a1b071dea4.html http://www.cnblogs.com/whiteyun/archive/2011/06/02/2067742.html ....
1. _beginthread也是通过CreateThread来创建线程的,只是_beginthread对其进行了一些封装,将相关”资源“通过线程的本地存储(TLS)传递给了线程函数的参数,然后在调用_endthread的时候,会将这些保存的资源进行释放。
2. 并不是所有的使用CreateThread的情况都会有内存泄漏。看了很多人的文章,只有http://wenku.baidu.com/view/adede4ec4afe04a1b071dea4.html的分析是最清晰的,我已经转到http://dl.dbank.com/c03ljl2iud了,可下载查看(版权归原作者所有)。
总之,建议是使用_beginthread取代CreateThread来创建线程。
(3)AfxBeginThread():
很显然,这是MFC中的Afx系列函数,一个在MFC中创建线程的全局函数。由于现在也不怎么用MFC了,这里就不多说了。
(4)CWinThread类:
很显然,是MFC中创建线程的类,同上,不多说了。
欢迎补充!
(1)补充内容:
关于WaitForMultipleObjects在_beginthread无法使用的问题
问题:使用_beginthread创建多个线程,无法使用WaitForMultipleObjects来进行同步。
这个问题可以用下面的例子来测试:
#include "stdafx.h" #include <Windows.h> #include <process.h> void __cdecl ThreadProc(void *para) { printf("sub thread started\n"); // TODO: Add your thread code here. printf("sub thread finished\n"); _endthread(); // 可以省略,隐含会调用。 } int main(int argc, char* argv[]) { DWORD threadID; HANDLE hThread[10]; for(int i =0;i<10;i++) hThread[i] = (HANDLE)_beginthread(ThreadProc,0,NULL); WaitForMultipleObjects(10, hThread,TRUE,INFINITE); //无法同步所有线程! for(int i = 0;i<10;i++) { CloseHandle(hThread); } }
_endthread()在结束线程的时候,会自动调用CloseHandle关闭内核对象。这就容易解释了,如果提前关闭了内核对象,WaitForMultipleObjects会返回错误。那么有没有专门用于_beginthread创建的线程的同步方法呢,就我目前所知,好象是没有的!要解决这里的问题,可以分别调用WaitForSingleObject来同步,当然,使用其他一些变相的方法也是可以的,另外,上面的CloseHandle当然就可以不用再调用了。
总结:看来_beginthread也不是那么好用。:)
(2)