线程的主要操作过程如下:创建线程,线程信息的获取,终止线程。
MFC中,线程分为工作者线程和用户界面线程。二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环。工作者线程没有消息机制,通常用来执行后台计算和维护任务,如冗长的计算过程,打印机的后台打印等。用户界面线程一般用于处理独立于其他线程执行之外的用户输入,响应用户及系统所产生的事件和消息等。但对于Win32的API编程而言,这两种线程是没有区别的,它们都只需线程的启动地址即可启动线程来执行任务。在MFC中,一般用全局函数AfxBeginThread()来创建并初始化一个线程的运行,该函数有两种重载形式,分别用于创建工作者线程和用户界面线程。两种重载函数原型和参数分别说明如下:
(1)PfnThreadProc:指向工作者线程的执行函数的指针,线程函数原型必须声明如下:CWinThread* AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam,//传递给线程函数的一个32位参数,执行函数将用某种方式解释该值。它可以是数值,或是指向一个结构的指针,甚至可以被忽略; nPriority=THREAD_PRIORITY_NORMAL,//线程的优先级。如果为0,则线程与其父线程具有相同的优先级; UINT nStackSize=0,//线程为自己分配堆栈的大小,其单位为字节。如果nStackSize被设为0,则线程的堆栈被设置成与父线程堆栈相同大小; DWORD dwCreateFlags=0,//如果为0,则线程在创建后立刻开始执行。如果为CREATE_SUSPEND,则线程在创建后立刻被挂起; LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);//线程的安全属性指针,一般为NULL;
UINT MyFuc(LPVOID pParam);
请注意,MyFuc()应返回一个UINT类型的值,用以指明该函数结束的原因。一般情况下,返回0表明执行成功。
(2)pThreadClass 是指向 CWinThread 的一个导出类的运行时类对象的指针, 该导出类定义了被创建的用户界面线程的启动、退出等;其它参数的意义同形式1。使用函数的这个原型生成的线程也有消息机制,在以后的例子中我们将发现同主线程的机制几乎一样。CWinThread* AfxBeginThread(CRuntimeClass* pThreadClass, int nPriority=THREAD_PRIORITY_NORMAL, UINT nStackSize=0, DWORD dwCreateFlags=0, LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);
下面就这两种现象很来模拟一个进度条:
- 用工作者线程来实现进度条:
相关的变量定义:
CEdit m_MyBaifenbi; CProgressCtrl m_MyProcess;
- 线程函数声明
UINT MyThread(LPVOID pParam);
- 线程函数定义
UINT MyThread(LPVOID pParam) { CMyThreadDlg *pDlg = (CMyThreadDlg*)pParam; CProgressCtrl *pPro = &pDlg->m_MyProcess; for (int n = 0;n<100;n++) { n++; pPro->SetPos(n); CString s; s.Format(_T("%d%%"),n); pDlg->m_Mybaifenbi.SetWindowText(s); Sleep(100); } return 0; }
- 线程函数调用
void CMyThreadDlg::OnMyBtn() { // TODO: Add extra validation here AfxBeginThread(MyThread,(LPVOID)this); }
2. 用用户界面线程来实现:
步骤:
- 首先要从类CwinThread产生一个派生类,同时必须使用DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE来声明和实现这个CwinThread派生类。
这一步自动生成;
- 第二步是根据需要重载该派生类的一些成员函数如:ExitInstance()、InitInstance()等函数。
本历程只是需要以下两个函数的重载:m_dlg是第三步需要创建的对话框类
//.h中 protected: CMyUIThread m_dlg;//duihuakuan //.cpp中 BOOL CMyThreadTwo::InitInstance() { // TODO: perform and per-thread initialization here m_dlg.Create(IDD_DIALOG1);//打开子对话框 m_dlg.ShowWindow(SW_SHOW);//显示 m_pMainWnd=&m_dlg;//保存子线程对话框实例句柄 return TRUE; } int CMyThreadTwo::ExitInstance() { // TODO: perform any per-thread cleanup here m_dlg.DestroyWindow(); return CWinThread::ExitInstance(); }
- 第三步创建一个对话框按下ctrl+w,自动生成一个对话框类。
在对话框里面创建一个进度条控件,一个静态文本控件(它需要改ID以后才能对其定义变量):
public: CMyUIThread(CWnd* pParent = NULL); // standard constructor // Dialog Data //{{AFX_DATA(CMyUIThread) enum { IDD = IDD_DIALOG1 }; CStatic m_MyBaifenbi; CProgressCtrl m_MyProcess;
在对话框上新建一个按钮控件,双击的到其响应函数,里面添加以下代码:
void CMyUIThread::OnButton2() { // TODO: Add your control notification handler code here m_MyProcess.SetRange(0,100); for (int n = 0;n<100;n++) { n++; m_MyProcess.SetPos(n); CString s; s.Format(_T("%d%%"),n); m_MyBaifenbi.SetWindowText(s); UpdateData(); Sleep(100); } }
- 最后调用AfxBeginThread()函数的一个版本:CWinThread* AfxBeginThread()启动该用户界面线程.