MFC中有两类线程,分别称之为工作者线程和用户界面线程。二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环。
工作者线程没笑消息机制,通常用来执行后台计算和维护任务,如冗长的计算过程,打印机的后台打印等。用户界面线程一般用于处理独立于其他线程之外的用户输入,响应用户及系统产生的事件和消息等。但对于Win32的API编程而言,这两种编程是没有区别的,他们都只需要线程的启动地址即可启动线程来执行任务。
在MFC中,一般用全局函数AfxBeginThread()来创建并初始化一个线程的运行,该函数有两种重载形式,分别用于创建工作者线程和用户界面线程。这两种函数的重载和原型分别说明如下:
(1)工作者线程
CWndThread *AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam, UINT nPriority=THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL);
(2)IU线程(用户界面线程)
CWndThread *AfxBeginThread(CRuntimeClass *pThreadClass, int nPriority=THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL);
AfxBeginThread()创建线程的流程不论哪个AfxBeginThread(),首先都是创建MFC线程对象,然后创建Win32线程对象。
AfxBeginThread创建线程的流程图
MFC线程技术剖析
MFC的核心类库中有一个名为CWinThread的类,这个类在MFC的底层机理中占举足轻重的地位。
MFC应用程序
线程状态用类_AFX_THREAD_STATE描述,模块状态用类_AFX_MODULE_STATE描述,模块-线程状态用类_AFX_MODULE_THREAD_STATE描述。这些类从类CNoTrackObject派生。进程状态用类_AFX_BASE_MODULE_STATE描述,从模块状态_AFX_MODULE_STATE派生。进程状态是一个可以独立执行的MFC应用程序的模块状态。还有其他状态如DLL的模块状态等也从模块状态类_AFX_MODULE_STATE派生。
MFC状态类的层次
模块、线程、模块-线程状态的关系
多线程实践案例:(多线程文件查找器)
查找文件的时候,首先用FindFirstFile函数,如果函数执行成功,返回句柄hFindFile来对应这个寻找操作,接下来可以利用这个句柄循环调用FindNextFile函数继续查找其他文件,知道该函数返回失败(FALSE)为止。最后还要调用FindClose函数关闭hFindFile句柄。
hFindFile = ::FindFirstFile(lpFileName,lpFindData); if(hFindFile != INVALID_HANDLE_VALUE) { do // 处理本次找到的文件 { }while(::FindNextFile(lpFileName,lpFindData)); ::FindColse(hFindFile); }
文件搜索器要在指定的目录及所有子层目录中查找文件,然后向用户显示出查找的结果。如果使用多线程的话,就意味着各线程要同时在不同目录中搜索文件。
这个程序最关键的地方是定义了一个动态的目录列表。
CTypedSimpleList<CDirectoryNode *> m_listDir; struct CDirectoryNode : public CNoTrackObject { CDirectoryNode* pNext; // CTypedSimpleList类模板要用次成员 char szDir[MAX_PATH]; //