MFC全局函数AfxBeginThread及其与CreateThread的区别(2009-08-1811:03:18)转载标签:afxbeginthreadcreatethreadit分类:技术函数功能描述:创建新的线程函数原型:CWinThread*AfxBeginThread(AFX_THREADPROCpfnThreadProc,LPVOIDpParam,intnPriority=THREAD_PRIORITY_NORMAL,UINTnStackSize=0,DWORDdwCreateFlags=0,LPSECURITY_ATTRIBUTESlpSecurityAttrs=NULL);CWinThread*AfxBeginThread(CRuntimeClass*pThreadClass,intnPriority=THREAD_PRIORITY_NORMAL,UINTnStackSize=0,DWORDdwCreateFlags=0,LPSECURITY_ATTRIBUTESlpSecurityAttrs=NULL);返回值:指向新创建的线程对象。参数:pfnThreadProc:工作线程的函数指针,不可以为空。并且工作线程的函数必须如此声明:UINTMyControllingFunction(LPVOIDpParam);pThreadClass:从CWinThread类继承来的对象的RUNTIME_CLASS指针。pParam:传递给工作线程函数pfnThreadProc的参数。nPriority:线程的优先级。如果为0,则与创建它的线程优先级相同。可以通过参考Win32Programmer’sReference中的SetThreadPriority得到所有可用的优先级列表和描述。nStackSize:以字节为单位指定新线程的堆栈大小。如果为0,则与创建它的线程的堆栈大小相同。dwCreateFlags:指定一个额外的标志控制线程的产生。它可以包括下面两个值中的一个:CREATE_SUSPENDED:以挂起模式开始线程,并且指定挂起次数.当调用ResumeThread时,这个线程才会被执行。0:创建之后,马上执行线程。lpSecurityAttrs:指向SECURITY_ATTRIBUTES结构的指针,结构中指定了线程的安全属性。如果为NULL,则与创建它的线程的安全属性相同。如果希望得到更多的有关SECURITY_ATTRIBUTES结构的信息,请参考Win32Programmer’sReference。注释:调用这个函数创建一个新的线程。第一种形式的AfxBeginThread创建一个工作线程;第二种形式创建一个用户接口线程。AfxBeginThread创建一个新的CWinThread对象,调用它的CreateThread函数开始执行线程并且返回指向线程的指针。Checksaremadethroughouttheproceduretomakesureallobjectsaredeallocatedproperlyshouldanypartofthecreationfail.终止线程,可以在线程函数中调用AfxEndThread,或者从工作线程的函数中返回。了解更多的有关AfxBeginThread的信息,可以参考文章Multithreading:CreatingWorkerThreads和Multithreading:CreatingUser-InterfaceThreadsinVisualC++Programmer’sGuide.参看:AfxGetThread示例:创建一个工作线程:UINTWorkForce(LPVOIDlpParameter);//线程函数声明CWinThread*pMyFirstWorker,*pMySecondWorker;LPVOIDpParam=NULL;intnPriority=THREAD_PRIORITY_ABOVE_NORMAL;//默认为THREAD_PRIORITY_NORMALUINTnStackSize=0;//与创建它的线程堆栈大小相同DWORDdwCreateFlags=0;//创建后立即执行LPSECURITY_ATTRIBUTESlpSecurityAttrs=NULL;//与创建它的线程安全属性相同pMyFirstWorker=AfxBeginThread((AFX_THREADPROC)WorkForce,pParam,nPriority,nStackSize,dwCreateFlags,lpSecurityAttrs);pMySecondWorker=AfxBeginThread((AFX_THREADPROC)WorkForce,pParam);//如果采用默认值DWORDWINAPIWorkForce(LPVOIDlpParameter//线程所需参数,可以通过它传递数据){return0;//什么不做}CWinThread*AfxBeginThread(CRuntimeClass*pThreadClass,intnPriority=THREAD_PRIORITY_NORMAL,UINTnStackSize=0,DWORDdwCreateFlags=0,LPSECURITY_ATTRIBUTESlpSecurityAttrs=NULL);参数说明:pfnThreadProc:线程函数的地址,该参数不能设置为NULL,线程函数必须定义成全局函数或者类的静态成员函数例如:UINTmyThreadFunc(LPVOIDlparam)或者classA{public:staticUINT__stdcallmyThreadFunc(LPVOIDlparam);}之所以要定义成类的静态成员函数,是因为类的静态成员函数不属于某个类对象,这样在调用函数的时候就不用传递一个额外的this指针.pThreadClass:指向从CWinThread派生的子类对象的RUNTIME_CLASSpParam:要传递给线程函数的参数nPriority:要启动的线程的优先级,默认优先级为THREAD_PRIORITY_NORMAL(普通优先级),关于线程优先级的详细说明请参考PlatformSDKSetThreadPriority函数说明nStackSize:新线程的堆栈大小,如果设置为0,则使用默认大小,在应用程序中一般情况下线程的默认堆栈大小为1MdwCreateFlags:线程创建标志,该参数可以指定为下列标志CREATE_SUSPENDED:以挂起方式启动线程,如果你在线程启动之前想初始化一些CWinThread类中的一些成员变量比如:m_bAutoDelete或者你的派生类中的成员变量,当初始化完成之后,你可以使用CWinThread类的ResumeThread成员函数来恢复线程的运行如果把该标志设置为0,则表示立即启动线程lpSecurityAttrs:指向安全描述符的指针,如果使用默认的安全级别只要讲该参数设置为NULL就可以了!上面就是AfxBeginThread函数的简单说明,我们在使用的时候一般情况下只要指定前两个参数,其他参数使用默认值就可以.嗯,的确,使用起来是很简单,只要这个函数一被调用,就创建了一个线程.但是大家有没有想过,AfxBeginThread函数究竟是如何启动的线程呢?它的内部是如何实现的呢?下面我们就来看一下AfxBeginThread函数的内部实现//启动worker线程CWinThread*AFXAPIAfxBeginThread(AFX_THREADPROCpfnThreadProc,LPVOIDpParam,intnPriority,UINTnStackSize,DWORDdwCreateFlags,LPSECURITY_ATTRIBUTESlpSecurityAttrs){#ifndef_MTpfnThreadProc;pParam;nPriority;nStackSize;dwCreateFlags;lpSecurityAttrs;returnNULL;#elseASSERT(pfnThreadProc!=NULL);CWinThread*pThread=DEBUG_NEWCWinThread(pfnThreadProc,pParam);ASSERT_VALID(pThread);if(!pThread-CreateThread(dwCreateFlags|CREATE_SUSPENDED,nStackSize,lpSecurityAttrs)){pThread-Delete();returnNULL;}VERIFY(pThread-SetThreadPriority(nPriority));if(!(dwCreateFlags&CREATE_SUSPENDED))VERIFY(pThread-ResumeThread()!=(DWORD)-1);returnpThread;#endif//!_MT)}//启动UI线程CWinThread*AFXAPIAfxBeginThread(CRuntimeClass*pThreadClass,intnPriority,UINTnStackSize,DWORDdwCreateFlags,LPSECURITY_ATTRIBUTESlpSecurityAttrs){#ifndef_MTpThreadClass;nPriority;nStackSize;dwCreateFlags;lpSecurityAttrs;returnNULL;#elseASSERT(pThreadClass!=NULL);ASSERT(pThreadClass-IsDerivedFrom(RUNTIME_CLASS(CWinThread)));CWinThread*pThread=(CWinThread*)pThreadClass-CreateObject();if(pThread==NULL)AfxThrowMemoryException();ASSERT_VALID(pThread);pThread-m_pThreadParams=NULL;if(!pThread-CreateThread(dwCreateFlags|CREATE_SUSPENDED,nStackSize,lpSecurityAttrs)){pThread-Delete();returnNULL;}VERIFY(pThread-SetThreadPriority(nPriority));if(!(dwCreateFlags&CREATE_SUSPENDED))VERIFY(pThread-ResumeThread()!=(DWORD)-1);returnpThread;#endif//!_MT}从上面的代码中可以看出AfxBeginThread所做的事情主要有以下几点:1.在heap中配置一个新的CWinThread对象(worker线程)代码如:CWinThread*pThread=DEBUG_NEWCWinThread(pfnThreadProc,pParam);调用CRuntimeClass结构中的CreateObject函数创建CWinThread对象CWinThread*pThread=(CWinThread*)pThreadClass-CreateObject();CRuntimeClass以及MFC相关类的内部实现,详情请参考《深入浅出MFC》侯捷著2.调用CWinThread::CreateThread()并设定属性,使线程以挂起状态产生pThread-CreateThread(dwCreateFlags|CREATE_SUSPENDED,nStackSize,lpSecurityAttrs);3.设定线程的优先权pThread-SetThreadPriority(nPriority);4.调用