按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
#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 LPSECURITY_ATTRIBUTES lpSecurityAttrs)
#0065 {
#0066 ASSERT(pThreadClass != NULL);
#0067 ASSERT(pThreadClass…》IsDerivedFrom(RUNTIME_CLASS(CWinThread)));
#0068
#0069 CWinThread* pThread = (CWinThread*)pThreadClass…》CreateObject();
#0070
#0071 pThread…》m_pThreadParams = NULL;
#0072 if (!pThread…》CreateThread (dwCreateFlags|CREATE_SUSPENDED; nStackSize;
#0073 lpSecurityAttrs))
#0074 {
#0075 pThread…》Delete();
#0076 return NULL;
#0077 }
#0078 VERIFY(pThread…》SetThreadPriority(nPriority));
#0079 if (!(dwCreateFlags & CREATE_SUSPENDED))
#0080 VERIFY(pThread…》ResumeThread() != (DWORD)…1);
#0081
#0082 return pThread;
#0083 }
#0084
#0085 BOOL CWinThread::CreateThread (DWORD dwCreateFlags; UINT nStackSize;
#0086 LPSECURITY_ATTRIBUTES lpSecurityAttrs)
#0087 {
#0088 // setup startup structure for thread initialization
#0089 _AFX_THREAD_STARTUP startup; memset(&startup; 0; sizeof(startup));
#0090 startup。pThreadState = AfxGetThreadState();
#0091 startup。pThread = this;
#0092 startup。hEvent = ::CreateEvent(NULL; TRUE; FALSE; NULL);
758
…………………………………………………………Page 821……………………………………………………………
14 MFC
第 章 多緒程式設計
#0093 startup。hEvent2 = ::CreateEvent(NULL; TRUE; FALSE; NULL);
#0094 startup。dwCreateFlags = dwCreateFlags;
#0095 。。。
#0096 // create the thread (it may or may not start to run)
#0097 m_hThread = (HANDLE)_beginthreadex (lpSecurityAttrs; nStackSize;
#0098 &_AfxThreadEntry; &startup; dwCreateFlags | CREATE_SUSPENDED; (UINT*)&m_nThreadID);
#0099 。。。
#0100 }
图14…5 CWinThread 的相关源代码
产生执行线程, 为什么不直接用::CreateThread 或_beginthreadex ? 为什么要透过
CWinThread 对象? 我想你可以轻易从MFC 源代码中看出, 因为
CWinThread::CreateThread 和AfxBeginThread 不只是::CreateThread 的一层包装,更做
了一些application framework 所需的内部数据初始化工作,并确保使用正确的C runtime
library 版本。源代码中有:
#ifndef _MT
。。。 // 做些设定工作,不产生执行线程,回返。
#else
。。。 // 真正产生执行线程,回返。
#endif //!_MT)
的动作,只是被我删去未列出而已。
接下来我要把worker thread 和UI thread 的产生步骤做个整理。它们都需要调用
AfxBeginThread 以产生一个CWinThread 对象,但如果要产生一个UI thread ,你还必须
先定义一个CWinThread 衍生类别。
产生一个Worker Thread
Worker thread 不牵扯使用者接口。你应该为它准备一个执行线程函数, 然后调用
AfxBeginThread :
759
…………………………………………………………Page 822……………………………………………………………
第篇 深入 MFC 程式設計
CWinThread AfxBeginThread ThreadFunc
* pThread = ( ; &Param);
。。。
UINT ThreadFunc (LPVOID pParam)
{
。。。
}
AfxBeginThread 事实上一共可以接受六个参数,分别是:
CWinThread* AFXAPI AfxBeginThread(AFX_THREADPROC pfnThreadProc;
LPVOID pParam;
int nPriority = THREAD_PRIORITY_NORMAL;
UINT nStackSize = 0;
DWORD dwCreateFlags = 0;
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL);
参数一pfnThreadProc 表示执行线程函数。参数二pParam 表示要传给执行线程函数的参
数。参数三nPriority 表示优先权的微调值,预设为THREAD_PRIORITY_NORMAL ,也
就是没有微调。参数四nStackSize 表示堆栈的大小,默认值0 则表示堆栈最大容量为
1MB。参数五dwCreateFlags 如果为默认值0,就表示执行线程产生后立刻开始执行;如
果其值为CREATE_SUSPENDED ,就表示执行线程产生后先暂停执行。之后你可以使用
CWinThread::ResumeThread 重新执行它。参数六lpSecurityAttrs 代表新执行线程的安全防
护属性。默认值NULL 表示此一属性与其产生者(也是个执行线程)的属性相同。
在这里我们遭遇到一个困扰。执行线程函数是由系统调用的,也就是个callback 函数,不
容许有this 指针参数。所以任何一般的C++ 类别成员函数都不能够拿来当做执行线程函
式。它必须是个全域函数,或是个C++ 类别的static 成员函数。其原因我已经在第6
章的「Callback 函数」一节中描述过了,而采用全域函数或是C++ static 成员函数,其
间的优劣因素我也已经在该节讨论过。
执行线程函数的类型AFX_THREADPROC 定义于AFXW