按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
MltiThrd 。这一节,我要介绍MFC 多线程程序的写法。
探索CWinThread
就像CWinApp 对象代表一个程序本身一样,CWinThread 对象代表一个执行线程本身。这
个MFC 类别我们曾经看过,第6章讲「MFC 程序的生死因果」时,讲到「CWinApp::Run
程序生命的活水源头」,曾经追踪过CWinApp::Run 的源头CWinThread::Run (里面有
一个消息循环)。可见程序的「执行事实」系发生在CWinThread 对象身上,而CWinThread
对象必须要(必然会)产生一个执行线程。
我希望「CWinThread 对象必须要(必然会)产生一个执行线程」这句话不会引起你的误会,
以为程序在application object (CWinApp 对象)的构造式必然有个动作最终调用到
CreateThread 或_beginthreadex 。不,不是这样。想想看,当你的Win32 程序执行起来,
你的程序并没有调用CreateProcess 为自己做出代表自己的那个进程,也没有调用
CreateThread 为自己做出代表自己的主执行线程(primary thread )的那个执行线程。为你的
程序产生第一个进程和执行线程,是系统加载器以及核心模块(KERNEL32 )合作的结果。
所以,再次循着第6章一步步剖析的步骤,MFC 程序的第一个动作是CWinApp::CWinApp
(比WinMain 还早),在那里没有「产生执行线程」的动作,而是已经开始在收集执行线程
755
…………………………………………………………Page 818……………………………………………………………
第篇 深入 MFC 程式設計
的相关信息了:
// in MFC 4。2 APPCORE。CPP
CWinApp::CWinApp(LPCTSTR lpszAppName)
{
。。。
// initialize CWinThread state
AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
AFX_MODULE_THREAD_STATE* pThreadState = pModuleState…》m_thread;
ASSERT(AfxGetThread() == NULL);
pThreadState…》m_pCurrentWinThread = this;
ASSERT(AfxGetThread() == this);
m_hThread = ::GetCurrentThread();
m_nThreadID = ::GetCurrentThreadId();
。。。
}
虽然MFC 程序只会有一个CWinApp 对象,而CWinApp 衍生自CWinThread,但并不
是说一个MFC 程序只能有一个CWinThread 对象。每当你需要一个额外的执行线程,不
应该在MFC 程序中直接调用::CreateThread 或_beginthreadex,应该先产生一个
CWinThread 对象,再调用其成员函数CreateThread 或全域函数AfxBeginThread 将执行
线程产生出来。当然, 现在你必然已经可以推测到,CWinThread::CreateThread 或
AfxBeginThread 内部调用了::CreateThread 或_beginthreadex (事实上答案是
_beginthreadex )。
这看起来颇有值得商议之处:为什么CWinThread 构造式不帮我们调用AfxBeginThread
呢?似乎CWinThread 为德不卒。
图14…5 就是CWinThread 的相关源代码。
756
…………………………………………………………Page 819……………………………………………………………
14 MFC
第 章 多緒程式設計
#0001 // in MFC 4。2 THRDCORE。CPP
#0002 CWinThread::CWinThread(AFX_THREADPROC pfnThreadProc; LPVOID pParam)
#0003 {
#0004 m_pfnThreadProc = pfnThreadProc;
#0005 m_pThreadParams = pParam;
#0006
#0007 monConstruct();
#0008 }
#0009
#0010 CWinThread::CWinThread()
#0011 {
#0012 m_pThreadParams = NULL;
#0013 m_pfnThreadProc = NULL;
#0014
#0015 monConstruct();
#0016 }
#0017
#0018 void CWinThread::monConstruct()
#0019 {
#0020 m_pMainWnd = NULL;
#0021 m_pActiveWnd = NULL;
#0022
#0023 // no HTHREAD until it is created
#0024 m_hThread = NULL;
#0025 m_nThreadID = 0;
#0026
#0027 // initialize message pump
#0028 #ifdef _DEBUG
#0029 m_nDisablePumpCount = 0;
#0030 #endif
#0031 m_msgCur。message = WM_NULL;
#0032 m_nMsgLast = WM_NULL;
#0033 ::GetCursorPos(&m_ptCursorLast);
#0034
#0035 // most threads are deleted when not needed
#0036 m_bAutoDelete = TRUE;
#0037
#0038 // initialize OLE state
#0039 m_pMessageFilter = NULL;
#0040 m_lpfnOleTermOrFreeLib = NULL;
#0041 }
#0042
#0043 CWinThread* AFXAPI AfxBeginThread (AFX_THREADPROC pfnThreadProc; LPVOID pParam;
#0044 int nPriority; UINT nStackSize; DWORD dwCreateFlags;
#0045 LPSECURITY_ATTRIBUTES lpSecurityAttrs)
#0046 {
757
…………………………………………………………Page 820……………………………………………………………
第篇 深入 MFC 程式設計
#0047 CWinThread* pThread = DEBUG_NEW CWinThread (pfnThreadProc; pParam);
#0048
#0049 if (!pThread…》CreateThread (dwCreateFlags|CREATE_SUSPENDED; nStackSize;
#0050 lpSecurityAttrs))
#0051 {
#0052 pThread…》Delete();
#0053 return NULL;
#0054 }
#0055 VERIFY(pThread…》SetThreadPriority(nPriority));
#0056 if (!(dwCreateFlags & CREATE_SUSPENDED))
#0057 VERIFY(pThread…》ResumeThread() != (DWORD)…1);
#0058
#0059 return pThread;
#0060 }
#0061
#0062 CWinThread* AFXAPI AfxBeginThread (CRuntimeClass* pThreadClass;
#0063 int nPriority; UINT nStackSize; DWORD dwCreateFlags;
#0064