MFC下的线程: 对Windows而言,所有的线程都是类似的;而在MFC中,则将线程分未了用户界面线程(UI Threads)和工作者线程(Worker Threads)。界面线程与工作者线程的主要区别在于:用户界面线程的程序代码中有消息循环,可处理从系统收到的消息,而工作者线程则没有收发消息的功能。 2.3.1 MFC线程类CWinThread 2.3.2 MFC线程的创建:调用AfxBeginThread函数。 2.3.2 .1创建用户界面线程 CWinThread* AfxBeginThread( CRuntimeClass* pThreadClass, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL ); 该函数使用了一个CWinThread派生类的运行时类替代了全局的线程函数。为什么用派生类,因为基类CWinThread的虚拟成员函数InitInstance()仅仅返回false,无法进入消息循环,故在创建用户界面线程时,必须指定一个重载了InitInstance()虚函数的CWinThread派生类。 2.3.2 .2创建工作者线程 CWinThread* AfxBeginThread( AFX_THREADPROC pfnThreadProc, LPVOID pParam, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL ); 也可以使用CWinThread类的CreateThread()方法。 BOOL CreateThread( DWORD dwCreateFlags = 0, UINT nStackSize = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL ); 在使用这个方法创建线程之前要做一些准备工作,即分别为线程对象的m_pfnThreadProc属性赋值,用来指明线程函数;然后为m_pThreadParams属性赋值,用来指定线程函数所需要的参数。完成这些步骤之后,即可通过构建好的CWinThread对象来调用CreateThread()方法完成线程的创建。简单示意如下: //定义全局的线程函数 UINT MyThreadProc(LPVOID pParam) { //Do something } //创建线程 CWinThread *CreateWorkerThread() { CWinThread *pThread=new CWinThread(); pThread->m_pfnThreadProc=MyThreadProc; pThread->m_pThreadParams=...;//赋值 if(!pThread-.CreateThread()) { pThread->Delete(); return NULL; } return pThread; } 2.3.2 .3AfxBeginThread在创建线程时,不论是用户界面线程还是工作者线程,都是先创建MFC线程对象,然后创建Win32线程对象。在创建MFC线程对象时,它们分别调用了不同的构造函数。 2.3.2 .4线程函数必须是一个全局函数(也可以是类的静态成员函数),该函数的唯一参数由AfxBeginThread()函数的参数pParam传递。 2.3.3 线程的挂起:一个运行中的线程可以通过调用CWinThread::SuspendThread()来挂起。一个线程可以在其自身上执行挂起操作,也可以通过另外的线程来调用其SuspendThread()。一个挂起的线程几乎不占用CPU的时间,也不增加系统的开销。对于每个线程,Windows为其保持一个挂起计数,每次调用SuspendThread()函数,该挂起计数就增加1.SuspendThread()函数的返回值是该线程的先前挂起计数。 CWinThread::ResumeThread()函数用来唤醒一个被挂起的线程。一个被挂起的线程不能调用该函数来唤醒自己,必须有别的线程为被挂起的线程调用这一函数。ResumeThread函数的返回值是该线程的先前挂起计数,当其返回值为1时,线程将会重新被执行。 一个线程可以通过调用API函数Sleep()使它自身休眠。休眠的线程不占用CPU时间,且能够在一段指定的时间后自动苏醒。其另一个用处是,::Sleep(0);这条语句将暂停当前的线程,并允许调度程序允许其他具有相同优先级的线程,如果没有相同优先级的线程正在等待执行,则该函数调用立即返回,并且调度程序重新运行当前的线程。 2.3.4 线程的结束: 2.3.4 .1正常终止线程:工作者线程与用户界面线程的终止方式不同。对于工作者线程,线程函数的正常退出(即执行了return语句)即为正常终止,此时线程函数返回一个退出代码。对于一个用户界面进程,一般通过发送WM_QUIT消息使得消息循环结束,进而退出线程;一个线程可以调用::PostQuitMessage()来向自身发送WM_QUIT消息,从而终止线程;也可以通过调用PostThreadMessage()向线程发送退出消息;如果用户界面创建了窗口,可以使用PostMessage()向该窗口发送退出消息来结束线程。 2.3.4 .2强行终止线程:调用函数AfxEndThread,它将清理本线程创建的MFC对象,释放线程分配的内存空间。它实际上是通过调用CWinThead的虚函数Delete()来释放分配给线程的资源,但是不关闭线程句柄。CWinThread::Delete()的缺省实现过程可以表述为:如果本线程的成员函数m_bDelete为TRUE,则调用Delete()销毁MFC线程对象自身,这将导致线程对象的析构函数被调用。若析构函数检测线程句柄非空,则调用CloseHandle()关闭它。可以调用GetExitCodeThread()函数,获取辅助线程的退出代码。 |
MFC下的线程(Windows环境下的多线程编程)
最新推荐文章于 2021-01-11 15:30:55 发布
Windows环境下的多线程编程