MFC下的线程(Windows环境下的多线程编程)

Windows环境下的多线程编程
 

MFC下的线程:

Windows而言,所有的线程都是类似的;而MFC中,则将线程分未了用户界面线程(UI Threads)和工作者线程(Worker Threads)。界面线程与工作者线程的主要区别在于:用户界面线程的程序代码中有消息循环,可处理从系统收到的消息,而工作者线程则没有收发消息的功能。

2.3.1MFC线程类CWinThread

2.3.2MFC线程的创建:调用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时间,且能够在一段指定的时间后自动苏醒。其另一个用处是,::Sleep0);这条语句将暂停当前的线程,并允许调度程序允许其他具有相同优先级的线程,如果没有相同优先级的线程正在等待执行,则该函数调用立即返回,并且调度程序重新运行当前的线程。

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_bDeleteTRUE,则调用Delete()销毁MFC线程对象自身,这将导致线程对象的析构函数被调用。若析构函数检测线程句柄非空,则调用CloseHandle()关闭它。可以调用GetExitCodeThread()函数,获取辅助线程的退出代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值