1.C语言函数,调用_beginthread();
2.API函数,调用CreateThread();(这个函数是_beginthread 和AfxBeginThread 根本 )
3.MFC函数,调用AfxBeginThread();
AfxBeginThread是MFC的全局函数,是对CreateThread的封装。
CreateThread是Win32 API函数,AfxBeginThread最终要调到CreateThread。
×××××××××××××××××××××××××××××××××××××××××××××××××××××××××
1>.
具体说来,CreateThread这个 函数是windows提供给用户的 API函数,是SDK的标准形式,在使用的过
程中要考虑到进程的同步与互斥的关系,进程间的同步互斥等一系列会导致操作系统死锁的因素,用起来
比较繁琐一些,初学的人在用到的时候可能会产生不可预料的错误,建议多使用AfxBeginThread,是编译
器对原来的CreateThread函数的封装,用与MFC编程(当然,只要修改了项目属性,console和win32项目
都能调用)而_beginthread是C的运行库函数。
2>
在使用AfxBeginThread时,
线程函数的定义为:UINT _yourThreadFun(LPVOID pParam)参数必须如此
在使用CreateThread时,
线程的函数定义为: DWORD WINAPI _yourThreadFun(LPVOID pParameter)
两者实质是一样的,
不过AfxBeginThread返回CWinThread指针,就是说它会new一个CWinThread对象,而这个对象在线程运行结束时是会自动删除的,
CreatThread,它返回的是一个句柄,如果你不使用CloseHandle的话就可以通过它安全的了解线程状态,
最后不要的时候CloseHandle,Windows才会释放资源。
_beginthreadex是微软的C/C++运行时库函数,CreateThread是操作系统的函数,_beginthreadex通过调用CreateThread来实现的,但比CreateThread多做了许多工作。
×××××××××××××××××××××××××××××××××××××
利用MFC里的AfxBeginThread函数能很方便地创建线程以及对线程进行等待、唤醒等操作。
1、函数原型
CWinThread* AfxBeginThread//返回值:一个指向新线程的线程对象。
(
AFX_THREADPROC pfnThreadProc ,//线程的入口函数,声明一定要如下:UINT MyThreadFunction( LPVOID pParam );
LPVOID pParam ,//传递入线程的参数,注意它的类型为:LPVOID,所以我们可以传递一个结构体入线程。
int nPriority = THREAD_PRIORITY_NORMAL ,//线程的优先级,一般设置为 0。让它和主线程具有共同的优先级。
UINT nStackSize = 0 ,//指定新创建的线程的栈的大小。如果为 0,新创建的线程具有和主线程一样的大小的栈。
DWORD dwCreateFlags = 0,//指定创建线程以后,线程有怎么样的标志。可以指定两个值:
//CREATE_SUSPENDED:线程创建以后,会处于挂起状态,直到调用ResumeThread;
//0:创建线程后就开始运行。
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL//指向一个 SECURITY_ATTRIBUTES 的结构体,用它来标志新创建线程的安全性
// 如果为 NULL,那么新创建的线程就具有和主线程一样的安全性。
);
线程创建
一般创建过程如下:
先定义一个工作函数,一般来说你的线程就是依照该函数的功能执行任务:
UINT MyThreadFunction( LPVOID pParam )
{
//函数体
return 0;
}
然后可以按以下方式创建线程:
CWinThread* MyThread=AfxBeginThread(MyThreadFunction , pParam , THREAD_PRIORITY_NORMAL , 0 , 0 , NULL);
4、线程的等待与唤醒
(1)让线程等待(暂时挂起):
MyThread->SuspendThread();
(2)唤醒暂停的线程:
MyThread->ResumeThread();
5、查看线程状态:
DWORD code;
GetExitCodeThread(MyThread->m_hThread , &code);
if(code==STILL_ACTIVE){//线程仍在执行}
else {//线程停止执行}
6、结束线程
TerminateThread(MyThread->m_hThread , 0);
×××××××××××××××××××××××××××××
CWinThread* AfxBeginThread
(
CRuntimeClass* pThreadClass,//工作线程的函数指针,不可以为空。并且工作线程的函数必须如此声明:
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);
×××××××××××××××××××××××××××××××××××××
××××××××××××××××××××××××××××××××××××××××××××××××××
CreateThread
函数功能:创建线程
函数原型:
HANDLEWINAPICreateThread(
LPSECURITY_ATTRIBUTESlpThreadAttributes,//表示线程内核对象的安全属性,一般传入NULL表示使用默认设置
SIZE_TdwStackSize,//表示线程栈空间大小。传入0表示使用默认大小(1MB)。
LPTHREAD_START_ROUTINElpStartAddress,//表示新线程所执行的线程函数地址,多个线程可以使用同一个函数地址。
LPVOIDlpParameter,//传给线程函数的参数。
DWORDdwCreationFlags,//指定额外的标志来控制线程的创建,为0表示线程创建之后立即就可以进行调度,
// 如果为CREATE_SUSPENDED则表示线程创建后暂停运行,这样它就无法调度,直到调用ResumeThread()。
LPDWORDlpThreadId//返回线程的ID号,传入NULL表示不需要返回该线程ID号。
);
函数返回值:成功返回新线程的句柄,失败返回NULL。
//最简单的创建多线程实例 #include <stdio.h> #include <windows.h> //子线程函数 DWORD WINAPI ThreadFun(LPVOID pM) { printf("子线程的线程ID号为:%d 子线程输出Hello World ", GetCurrentThreadId()); return 0; } //主函数,所谓主函数其实就是主线程执行的函数。 int main() { printf(" 最简单的创建多线程实例 "); printf(" -- by MoreWindows( http://blog.csdn.net/MoreWindows ) -- "); HANDLE handle = CreateThread(NULL, 0, ThreadFun, NULL, 0, NULL); WaitForSingleObject(handle, INFINITE); return 0; }
××××××××××××××××××××××××××××××××××××××××
AfxBeginThread和CreateThread具体区别
具体说来,CreateThread这个 函数是windows提供给用户的 API函数,是SDK的标准形式,在使用的过程中要考虑到进程的同步与互斥的关系,进程间的同步互斥等一系列会导致操作系统死锁的因素,用起来比较繁琐一些,初学的人在用到的时候可能会产生不可预料的错误,建议多使用AfxBeginThread,是编译器对原来的CreateThread函数的封装,用与MFC编程(当然,只要修改了项目属性,console和win32项目都能调用)而_beginthread是C的运行库函数。
在使用AfxBeginThread时,线程函数的定义为:
两个的实质都是一样的,不过AfxBeginThread返回一个CWinThread的指针,就是说他会new一个CWinThread对象,而且这个对象是自动删除的(在线程运行结束时),给我们带来的不便就是无法获得它的状态,因为随时都有可能这个指针指向的是一个已经无效的内存区域,所以使用时(如果需要了解它的运行状况的话)首先CREATE_SUSPENDED让他挂起,然后m_bAutoDelete=FALSE,接着才ResumeThread,最后不要了delete那个指针。
CreatThread就方便多了,它返回的是一个句柄,如果你不使用CloseHandle的话就可以通过他安全的了解线程状态,最后不要的时候CloseHandle,Windows才会释放资源,所以我一般使用CreatThread,方便。
如果用MFC编程,不要用CreateThread,如果只是使用Runtime Library,用_BegingThread,总之,不要轻易使用CreateThread。这是因为在MFC和RTL中的函数有可能会用到些它们所封装的公用变量,也就是说AfxBeginThread和_BeginThread都有自己的启动代码是CreateThread所没有的。
在用CreateThread所创建的线程中使用MFC的类和RTL函数就有可能出现问题。如果你是用汇编编写win32程序并且在线程函数中也不调用MFC和RTL的函数,那用CreateThread就没问题,或者你虽然是用C写线程函数,但你很小心没调用RTL函数也不会有问题。
CreateThread是由操作系统提供的接口,而AfxBeginThread和_BeginThread则是编译器对它的封装。
在可能的情况下,不要调用_beginthread,而应该调用_beginthreadex。以及对应的_endthreadex。这都是C++运行期函数。但是使用_beginthread,无法创建带有安全属性的新线程,无法创建暂停的线程,也无法获得线程ID,_endthread的情况类似,它不带参数,
这意味这线程的退出代码必须硬编码为0。这两个函数在_beginthreadex和_endthreadex中进行调用。CreateThread不要进行直接调用。