1. 程式人生 > >二十一天學通VC++之建立使用者介面執行緒

二十一天學通VC++之建立使用者介面執行緒

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

建立使用者介面執行緒

本人節選自《21天學通C++》一書

 

    與工作者執行緒不同的是,使用者介面執行緒通常用於處理使用者的輸入,響應使用者產生的訊息。為了建立一個使用者介面執行緒,需要從CWinThread引出自定義的類,並將該類的執行時資訊傳給使用者介面形式的AfxBeginThread函式,以便建立使用者介面執行緒。
一般來說,使用者介面執行緒的建立過程需要先從基類CWinThread中派生出使用者自定義的新類,再使用AfxBeginThread函式建立執行緒。
【範例17-1】下面將通過一個例項來講述如何建立一個使用者介面執行緒。該例項實現建立一個獨立於應用程式的視窗,其具體操作步驟如下所述。
 新建一個MFC單文件應用程式。單擊【File】|【New】選單項,開啟新建對話方塊,選擇建立【MFCAppWizard[exe]】工程,為工程命名為“建立執行緒”。在AppWizard的第一步中選中【Singledocument】,其他步驟按照預設設定,單擊【Finish】按鈕完成建立。
  新增選單項。為了演示出該例項建立獨立於應用程式的使用者介面執行緒,在該工程中新增新的選單項“使用者介面執行緒”用於建立和啟動執行緒。具體操作為:
開啟工作區的【ResourceView】選項卡,修改MFC應用程式嚮導自動生成的選單資源。在原選單基礎上再新增一個彈出式選單“執行緒”。在其下面新增選單項“使用者介面執行緒”,設定其ID為ID_THREAD_GUI,如圖17-3所示。
 從CWinThread中派生新類。派生新類的方法很簡單,在以前章節中也介紹過。可以使用ClassWizard工具單擊【AddClass】|【New】命令,也可以通過開啟工作區【ClassView】選項卡。右鍵單擊最頂層類集,在彈出的快捷方式選單中選擇【NewClass】選單項來啟動【NewClass】對話方塊。在基類列表框中選擇CWindThread類,然後在【Name】文字框中輸入派生類名。該例項定義其派生類為MyThread。
單擊【OK】按鈕後即建立了CWinThread類的派生類MyThread。此時讀者在工作臺的【FileView】標籤中找到MyThread.h檔案,開啟後可看到如下的類定義。
// MyThread thread
class MyThread : public CWinThread
{
    DECLARE_DYNCREATE(MyThread)
protected:
    MyThread();          
    ……
    DECLARE_MESSAGE_MAP()
};

說明:程式碼中使用了DECLARE_DYNCREATE巨集,使用該巨集表明MyThread類具有動態建立的能力。使用DECLARE_MESSAGE_MAP巨集表明具有訊息對映,可以處理命令訊息。
再開啟MyThread類的實現檔案(MyThread.cpp)。下面列出其中一部分程式碼。
// MyThread
IMPLEMENT_DYNCREATE(MyThread, CWinThread)

MyThread::MyThread()
{
}
……
BEGIN_MESSAGE_MAP(MyThread, CWinThread)
END_MESSAGE_MAP()

提示:程式碼中使用了IMPLEMENT_DYNCREATE巨集是和標頭檔案中DECLARE_DYNCREATE巨集相對應的,其保證新建的類具有動態建立的能力。而BEGIN_MESSAGE_MAP和END_MESSAGE_MAP巨集是和標頭檔案中DECLARE_MESSAGE_MAP巨集相對應的,使類具有訊息對映機制。
 過載CWinThread的虛擬函式。基類CWinThread有一些可以過載的虛擬函式。其中InitInstance函式必須要過載,該函式用於初始化例項。ExitInstance函式一般情況下也應該過載,該函式用於清除例項。而Run函式,如果沒有特殊需要,一般不去過載。該函式負責將訊息分發出去。過載InitInstance函式如示例程式碼17-1所示。
示例程式碼17-1
01    BOOL MyThread::InitInstance()
02    {
03        // TODO:  perform and per-thread initialization here
04        CFrameWnd* pFrameWnd= new CFrameWnd();                    //定義框架物件
05        pFrameWnd->CreateEx(0,AfxRegisterWndClass( CS_HREDRAW|CS_VREDRAW) ,
06                "使用者介面執行緒示例",   
07                WS_OVERLAPPEDWINDOW|WS_VISIBLE,
08                CRect(100,100,400,300),
09                NULL,
10                0);                                             //建立視窗
11        m_pMainWnd=pFrameWnd;
12        pFrameWnd->ShowWindow(SW_SHOW);                        //顯示視窗
13        pFrameWnd->UpdateWindow();
14        return TRUE;
15    }
 使用AfxBeginThread函式建立並啟動執行緒物件。在CMyView類中,新增新建選單項的COMMAND命令訊息處理函式OnThreadGui。新增方法為:右鍵單擊CMyView類,選擇【Add Windows MessageHandle】選單項,進入新增訊息處理函式對話方塊。在【Class or ObjectIDS】下拉列表框中選擇選單項ID_Thread_Gui,事件則選擇【COMMAND】並雙擊。
  單擊【OK】按鈕新增完成。單擊【Edit Existing】按鈕進入程式碼編輯器介面。在該訊息處理函式中通過呼叫AfxBeginThread函式來啟動使用者介面執行緒,程式碼如下:
void CMyView::OnThreadGui()
{
    // TODO: Add your command handler code here
    AfxBeginThread(RUNTIME_CLASS(MyThread));                //啟動使用者介面執行緒
}
程式碼中又用到了AfxBeginThread函式,但是建立工作者執行緒和建立使用者介面執行緒的AfxBeginThread函式的形式是有一定區別的。在這段程式碼裡,用的是建立使用者介面執行緒的AfxBeginThread函式。

警告:因為在檢視類CMyView中用到了新建的執行緒類MyThread。因此,最後不要忘記在CMyView類中包含MyThread類的標頭檔案。具體程式碼如下:
#include "MyThread.h"
【執行結果】在Visual C++ 6.0中編譯後無錯誤,使用快捷鍵【Ctrl+F5】執行該工程。
【程式碼解析】在上述程式碼中,第4行首先構造了一個框架視窗物件。然後在第5~10行呼叫其成員函式CreateEx來產生視窗。最後將視窗顯示出來。如果使用者介面執行緒正常執行時,就會產生一個標題為“使用者介面執行緒示例”的視窗。讀者可以發現,新建的使用者介面執行緒視窗顯示在螢幕上。

說明:需要讀者瞭解的是,這個執行緒視窗不屬於建立執行緒程式的主框架視窗,而是和主框架視窗(也可以說是主執行緒視窗)並列的。兩者的父視窗都是系統的桌面。檢視桌面底部的Windows系統工作列就會發現,除了建立執行緒應用程式視窗,也有單獨的使用者介面執行緒視窗。
此時,這兩個視窗可以並行工作,互不影響。使用者可以單獨關閉子視窗使用者介面執行緒視窗,就相當於正常退出了該子執行緒視窗,不會對主執行緒建立程序視窗造成影響。反過來,如果使用者關閉主執行緒視窗,則使用者介面執行緒視窗也會被迫關閉。這種情況屬於使用者介面執行緒非正常退出,會造成記憶體洩漏。

           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述