三、MFC多線程編程實例
在Visual C++
6.0編程環境中,我們既可以編寫C風格的32位Win32應用程序,也可以利用MFC類庫編寫C++風格的應用程序,二者各有其優缺點。
基于Win32的應用程序執行代碼小巧,運行效率高,但要求程序員編寫的代碼較多,且需要管理系統提供給程序的所有資源;而基于MFC類庫的應用程序可以快速建立起應用程序,類庫為程序員提供了大量的封裝類,而且DeveloperStudio為程序員提供了一些工具來管理用戶源程序,其缺點是類庫代碼很龐大。由于使用類庫所帶來的快速、簡捷和功能強大等優越性,因此除非有特殊的需要,否則VisualC++推薦使用MFC類庫進行程序開發。
我們知道,MFC中的線程分為兩種:用戶界面線程和工作者線程。我們將分別舉例說明。
用 MFC 類庫編程實現工作者線程
例程5 MultiThread5
為了與Win32 API對照,我們使用MFC 類庫編程實現例程3 MultiThread3。
建立一個基于對話框的工程MultiThread5,在對話框IDD_MULTITHREAD5_DIALOG中加入一個編輯框 IDC_MILLISECOND,一個按鈕IDC_START,標題為“開始” ,一個進度條IDC_PROGRESS1;
打開 ClassWizard,為編輯框IDC_MILLISECOND添加int型變量m_nMilliSecond,為進度條IDC_PROGRESS1添加CProgressCtrl型變量m_ctrlProgress;
在MultiThread5Dlg.h文件中添加一個結構的定義: struct threadInfo
{
UINT nMilliSecond;
CProgressCtrl* pctrlProgress;
};
線程函數的聲明:UINT ThreadFunc(LPVOID lpParam);
注意,二者應在類CMultiThread5Dlg 的外部。
在類CMultiThread5Dlg內部添加protected型變量:
CWinThread* pThread;
在MultiThread5Dlg.cpp文件中進行如下操作:定義公共變量:threadInfo Info;
雙擊按鈕IDC_START,添加相應消息處理函數:
void CMultiThread5Dlg::OnStart()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
Info.nMilliSecond=m_nMilliSecond;
Info.pctrlProgress=&m_ctrlProgress;
pThread=AfxBeginThread(ThreadFunc,
&Info);
}
在函數BOOL CMultiThread3Dlg::OnInitDialog()中添加語句: {
……
// TODO: Add extra initialization here
m_ctrlProgress.SetRange(0,99);
m_nMilliSecond=10;
UpdateData(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
}
添加線程處理函數: UINT ThreadFunc(LPVOID lpParam)
{
threadInfo* pInfo=(threadInfo*)lpParam;
for(int i=0;i《100;i++)
{
int nTemp=pInfo-》nMilliSecond;
pInfo-》pctrlProgress-》SetPos(i);
Sleep(nTemp);
}
return 0;
}
用 MFC 類庫編程實現用戶界面線程
創建用戶界面線程的步驟:
使用ClassWizard創建類CWinThread的派生類(以CUIThread類為例) class CUIThread : public CWinThread
{
DECLARE_DYNCREATE(CUIThread)
protected:
CUIThread(); // protected constructor used by dynamic creation
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CUIThread)
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
//}}AFX_VIRTUAL
// Implementation
protected:
virtual ~CUIThread();
// Generated message map functions
//{{AFX_MSG(CUIThread)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
重載函數InitInstance()和ExitInstance()。 BOOL CUIThread::InitInstance()
{
CFrameWnd* wnd=new CFrameWnd;
wnd-》Create(NULL,“UI Thread Window”);
wnd-》ShowWindow(SW_SHOW);
wnd-》UpdateWindow();
m_pMainWnd=wnd;
return TRUE;
}
創建新的用戶界面線程 void CUIThreadDlg::OnButton1()
{
CUIThread* pThread=new CUIThread();
pThread-》CreateThread();
}
請注意以下兩點:
A、在UIThreadDlg.cpp的開頭加入語句: #include “UIThread.h”
B、把UIThread.h中類 CUIThread()的構造函數的特性由 protected 改為 public。
用戶界面線程的執行次序與應用程序主線程相同,首先調用用戶界面線程類的InitInstance()函數,如果返回TRUE,繼續調用線程的Run()函數,該函數的作用是運行一個標準的消息循環,并且當收到WM_QUIT消息后中斷,在消息循環過程中,Run()函數檢測到線程空閑時(沒有消息),也將調用OnIdle()函數,最后Run()函數返回,MFC調用ExitInstance()函數清理資源。
你可以創建一個沒有界面而有消息循環的線程,例如:你可以從CWinThread 派生一個新類,在InitInstance函數中完成某項任務并返回FALSE,這表示僅執行InitInstance函數中的任務而不執行消息循環,你可以通過這種方法,完成一個工作者線程的功能。
評論