在MFC中,我們可以用到的一個API是AfxBeginThread,它的函數聲明原型如下:
CWinThread* AfxBeginThread(
AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);
CWinThread* AfxBeginThread(
CRuntimeClass* pThreadClass,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);
這兩個函數中,第一個可以創建一個用戶工作線程,第二個可以創建一個用戶界面線程。參數說明如下:
- pfnThreadProc: 指向工作線程的函數地址,函數格式爲UINT __cdecl MyControllingFunction( LPVOID pParam );
- pThreadClass: 用戶界面線程類,一般是從CWinThread繼承而來
- pParam: 需要傳給線程的參數
- nPriority: 優先級屬性標識符,詳見SetThreadPriority 中對其的描述,一般可設爲NULL
- nStackSize: 線程棧大小,如果設置爲0的話,就和創建線程棧大小一樣
- dwCreateFlags: 創建標識符,如果設爲CREATE_SUSPENDED ,線程在創建之後會掛起,期間你可以初始化一些變量之類的東西,它會等待直到你調用了CWinThread::ResumeThread 後才繼續執行。如果設置爲0 則線程創建之後立即執行。
- lpSecurityAttrs: 安全屬性標識符,可參看SECURITY_ATTRIBUTES 結構體實例化它,一般情況下可以設置爲NULL,表示使用和創建線程相同的安全屬性。
- 由MSDN可以看到,這個函數仍然也是調用了CreateThread函數來創建線程的,它與CreateThread不同的地方是它也如C++運行庫中的_beginthread一樣,需要做一些初始化工作,所以,在MFC的程序中,他的操作性要比CreateThread容易一些,不容易出錯。
- 對於線程的終止和返回,可以參看多線程編程(一)——CreateThread 和MSDN中的說明,此處不在做過多解釋。
-
下面舉例說明用法:
UserInterfaceThread.h
- #pragma once
- #include "afxwin.h"
- class CUserInterfaceThread : public CWinThread
- {
- DECLARE_DYNCREATE(CUserInterfaceThread)
- public:
- CUserInterfaceThread(void);
- ~CUserInterfaceThread(void);
- virtual BOOL InitInstance();
- virtual int ExitInstance();
- };
UserInterfaceThread.cpp
- #include "UserInterfaceThread.h"
- IMPLEMENT_DYNCREATE(CUserInterfaceThread, CWinThread)
- CUserInterfaceThread::CUserInterfaceThread(void)
- {
- }
- CUserInterfaceThread::~CUserInterfaceThread(void)
- {
- }
- BOOL CUserInterfaceThread::InitInstance()
- {
- // TODO: 在此添加專用代碼和/或調用基類
- MessageBox(NULL, _T("你好,這是用戶界面線程!"), _T("歡迎"), MB_OK);
- return CWinThread::InitInstance();
- }
- int CUserInterfaceThread::ExitInstance()
- {
- // TODO: 在此添加專用代碼和/或調用基類
- return CWinThread::ExitInstance();
- }
AFXThreading.h
- #ifndef MULTITHREAD
- #define MULTITHREAD
- class DrawPicture
- {
- public:
- static UINT MyThreadFunc(LPVOID lpParam );
- void Draw();
- private:
- static int nPoint;
- };
- #endif
AFXThreading.cpp
- #include <iostream>
- #include <afxwin.h>
- #include "AFXThreading.h"
- #include "UserInterfaceThread.h"
- using namespace std;
- int DrawPicture::nPoint = 20;
- UINT DrawPicture::MyThreadFunc( LPVOID lpParam )
- {
- while(nPoint > 0)
- {
- cout<<"It is Point:"<<nPoint--<<endl;
- }
- //AfxEndThread(0); //儘量避免使用,讓線程自動正常退出
- return 0;
- }
- void DrawPicture::Draw()
- {
- #pragma region 創建用戶工作線程
- AfxBeginThread(MyThreadFunc, 0, 0, 0, NULL);
- #pragma endregion 創建用戶工作線程
- #pragma region 創建用戶界面線程
- CUserInterfaceThread *pInterfaceThread = (CUserInterfaceThread*)AfxBeginThread(
- RUNTIME_CLASS(CUserInterfaceThread),
- THREAD_PRIORITY_NORMAL,
- 0,
- CREATE_SUSPENDED,
- NULL
- );
- if (NULL != pInterfaceThread)
- {
- pInterfaceThread->ResumeThread();//恢復線程
- }
- #pragma endregion 創建用戶界面線程
- }
- int main(void)
- {
- DrawPicture *pDraw = new DrawPicture;
- pDraw->Draw();
- delete pDraw;
- system("pause");
- return 0;
- }
應當注意的是,在創建用戶界面線程的時候,必須首先從 CWinThread 派生類。必須使用 DECLARE_DYNCREATE 和 IMPLEMENT_DYNCREATE 宏聲明並實現此類。此類必須重寫某些函數(InitInstance ),也可以重寫其他函數(ExitInstance )。詳情參看MSDN中《多線程處理:創建用戶界面線程》一文。