• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            yehao's Blog

            多線程編程之二——MFC中的多線程開發(fā)

            五、MFC對多線程編程的支持

              MFC中有兩類線程,分別稱之為工作者線程和用戶界面線程。二者的主要區(qū)別在于工作者線程沒有消息循環(huán),而用戶界面線程有自己的消息隊列和消息循環(huán)。
              工作者線程沒有消息機制,通常用來執(zhí)行后臺計算和維護任務,如冗長的計算過程,打印機的后臺打印等。用戶界面線程一般用于處理獨立于其他線程執(zhí)行之外的用戶輸入,響應用戶及系統(tǒng)所產(chǎn)生的事件和消息等。但對于Win32的API編程而言,這兩種線程是沒有區(qū)別的,它們都只需線程的啟動地址即可啟動線程來執(zhí)行任務。
              在MFC中,一般用全局函數(shù)AfxBeginThread()來創(chuàng)建并初始化一個線程的運行,該函數(shù)有兩種重載形式,分別用于創(chuàng)建工作者線程和用戶界面線程。兩種重載函數(shù)原型和參數(shù)分別說明如下:

            (1) CWinThread* AfxBeginThread(AFX_THREADPROC pfnThreadProc,
            LPVOID pParam,
            nPriority=THREAD_PRIORITY_NORMAL,
            UINT nStackSize=0,
            DWORD dwCreateFlags=0,
            LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);
            
            PfnThreadProc:指向工作者線程的執(zhí)行函數(shù)的指針,線程函數(shù)原型必須聲明如下:
            UINT ExecutingFunction(LPVOID pParam);
            
            請注意,ExecutingFunction()應返回一個UINT類型的值,用以指明該函數(shù)結束的原因。一般情況下,返回0表明執(zhí)行成功。
            • pParam:傳遞給線程函數(shù)的一個32位參數(shù),執(zhí)行函數(shù)將用某種方式解釋該值。它可以是數(shù)值,或是指向一個結構的指針,甚至可以被忽略;
            • nPriority:線程的優(yōu)先級。如果為0,則線程與其父線程具有相同的優(yōu)先級;
            • nStackSize:線程為自己分配堆棧的大小,其單位為字節(jié)。如果nStackSize被設為0,則線程的堆棧被設置成與父線程堆棧相同大小;
            • dwCreateFlags:如果為0,則線程在創(chuàng)建后立刻開始執(zhí)行。如果為CREATE_SUSPEND,則線程在創(chuàng)建后立刻被掛起;
            • lpSecurityAttrs:線程的安全屬性指針,一般為NULL;
             (2) CWinThread* AfxBeginThread(CRuntimeClass* pThreadClass,
            int nPriority=THREAD_PRIORITY_NORMAL,
            UINT nStackSize=0,
            DWORD dwCreateFlags=0,
            LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);
            

             

              pThreadClass 是指向 CWinThread 的一個導出類的運行時類對象的指針,該導出類定義了被創(chuàng)建的用戶界面線程的啟動、退出等;其它參數(shù)的意義同形式1。使用函數(shù)的這個原型生成的線程也有消息機制,在以后的例子中我們將發(fā)現(xiàn)同主線程的機制幾乎一樣。

            下面我們對CWinThread類的數(shù)據(jù)成員及常用函數(shù)進行簡要說明。

            • m_hThread:當前線程的句柄;
            • m_nThreadID:當前線程的ID;
            • m_pMainWnd:指向應用程序主窗口的指針
            BOOL CWinThread::CreateThread(DWORD dwCreateFlags=0,
            UINT nStackSize=0,
            LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);
            

              該函數(shù)中的dwCreateFlags、nStackSize、lpSecurityAttrs參數(shù)和API函數(shù)CreateThread中的對應參數(shù)有相同含義,該函數(shù)執(zhí)行成功,返回非0值,否則返回0。
              一般情況下,調(diào)用AfxBeginThread()來一次性地創(chuàng)建并啟動一個線程,但是也可以通過兩步法來創(chuàng)建線程:首先創(chuàng)建CWinThread類的一個對象,然后調(diào)用該對象的成員函數(shù)CreateThread()來啟動該線程。

            virtual BOOL CWinThread::InitInstance();
            
              重載該函數(shù)以控制用戶界面線程實例的初始化。初始化成功則返回非0值,否則返回0。用戶界面線程經(jīng)常重載該函數(shù),工作者線程一般不使用InitInstance()。
            virtual int CWinThread::ExitInstance();
            
              在線程終結前重載該函數(shù)進行一些必要的清理工作。該函數(shù)返回線程的退出碼,0表示執(zhí)行成功,非0值用來標識各種錯誤。同InitInstance()成員函數(shù)一樣,該函數(shù)也只適用于用戶界面線程。

            六、MFC多線程編程實例

              在Visual C++ 6.0編程環(huán)境中,我們既可以編寫C風格的32位Win32應用程序,也可以利用MFC類庫編寫C++風格的應用程序,二者各有其優(yōu)缺點。基于Win32的應用程序執(zhí)行代碼小巧,運行效率高,但要求程序員編寫的代碼較多,且需要管理系統(tǒng)提供給程序的所有資源;而基于MFC類庫的應用程序可以快速建立起應用程序,類庫為程序員提供了大量的封裝類,而且Developer Studio為程序員提供了一些工具來管理用戶源程序,其缺點是類庫代碼很龐大。由于使用類庫所帶來的快速、簡捷和功能強大等優(yōu)越性,因此除非有特殊的需要,否則Visual C++推薦使用MFC類庫進行程序開發(fā)。

            我們知道,MFC中的線程分為兩種:用戶界面線程和工作者線程。我們將分別舉例說明。

            用 MFC 類庫編程實現(xiàn)工作者線程

            例程5 MultiThread5

            為了與Win32 API對照,我們使用MFC 類庫編程實現(xiàn)例程3 MultiThread3。

            1. 建立一個基于對話框的工程MultiThread5,在對話框IDD_MULTITHREAD5_DIALOG中加入一個編輯框IDC_MILLISECOND,一個按鈕IDC_START,標題為“開始” ,一個進度條IDC_PROGRESS1;
            2. 打開ClassWizard,為編輯框IDC_MILLISECOND添加int型變量m_nMilliSecond,為進度條IDC_PROGRESS1添加CProgressCtrl型變量m_ctrlProgress;
            3. 在MultiThread5Dlg.h文件中添加一個結構的定義:
              struct threadInfo
                  {
                  UINT nMilliSecond;
                  CProgressCtrl* pctrlProgress;
                  };
                  
              線程函數(shù)的聲明:
              UINT ThreadFunc(LPVOID lpParam); 

              注意,二者應在類CMultiThread5Dlg的外部。

              在類CMultiThread5Dlg內(nèi)部添加protected型變量:

              CWinThread* pThread; 
            4. 在MultiThread5Dlg.cpp文件中進行如下操作:定義公共變量:
              threadInfo Info; 

              雙擊按鈕IDC_START,添加相應消息處理函數(shù):

              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);
                  }
                  
              在函數(shù)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
                  }
                  
              添加線程處理函數(shù):
              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 類庫編程實現(xiàn)用戶界面線程

            創(chuàng)建用戶界面線程的步驟:

            1. 使用ClassWizard創(chuàng)建類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()
                  };
                  
            2. 重載函數(shù)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;
                  }
                  
              創(chuàng)建新的用戶界面線程
              void CUIThreadDlg::OnButton1()
                  {
                  CUIThread* pThread=new CUIThread();
                  pThread->CreateThread();
                  }
                  
              請注意以下兩點:

              A、在UIThreadDlg.cpp的開頭加入語句:
              #include "UIThread.h"
              B、把UIThread.h中類CUIThread()的構造函數(shù)的特性由 protected 改為 public。

                用戶界面線程的執(zhí)行次序與應用程序主線程相同,首先調(diào)用用戶界面線程類的InitInstance()函數(shù),如果返回TRUE,繼續(xù)調(diào)用線程的Run()函數(shù),該函數(shù)的作用是運行一個標準的消息循環(huán),并且當收到WM_QUIT消息后中斷,在消息循環(huán)過程中,Run()函數(shù)檢測到線程空閑時(沒有消息),也將調(diào)用OnIdle()函數(shù),最后Run()函數(shù)返回,MFC調(diào)用ExitInstance()函數(shù)清理資源。
                你可以創(chuàng)建一個沒有界面而有消息循環(huán)的線程,例如:你可以從CWinThread派生一個新類,在InitInstance函數(shù)中完成某項任務并返回FALSE,這表示僅執(zhí)行InitInstance函數(shù)中的任務而不執(zhí)行消息循環(huán),你可以通過這種方法,完成一個工作者線程的功能。

            例程6 MultiThread6

            1. 建立一個基于對話框的工程MultiThread6,在對話框IDD_MULTITHREAD6_DIALOG中加入一個按鈕IDC_UI_THREAD,標題為“用戶界面線程”
            2. 右擊工程并選中“New Class…”為工程添加基類為CWinThread派生線程類CUIThread。
            3. 給工程添加新對話框IDD_UITHREADDLG,標題為“線程對話框”。
            4. 為對話框IDD_UITHREADDLG創(chuàng)建一個基于CDialog的類CUIThreadDlg。使用ClassWizard為CUIThreadDlg類添加WM_LBUTTONDOWN消息的處理函數(shù)OnLButtonDown,如下:
              void CUIThreadDlg::OnLButtonDown(UINT nFlags, CPoint point)
                  {
                  AfxMessageBox("You Clicked The Left Button!");
                  CDialog::OnLButtonDown(nFlags, point);
                  }
            5. 在UIThread.h中添加
              #include "UIThreadDlg.h"
              并在CUIThread類中添加protected變量CUIThread m_dlg:
              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:
                  CUIThreadDlg m_dlg;
                  virtual ~CUIThread();
                  // Generated message map functions
                  //{{AFX_MSG(CUIThread)
                  // NOTE - the ClassWizard will add and remove member functions here.
                  //}}AFX_MSG
                  DECLARE_MESSAGE_MAP()
                  };
                  
            6. 分別重載InitInstance()函數(shù)和ExitInstance()函數(shù):
              BOOL CUIThread::InitInstance()
                  {
                  m_dlg.Create(IDD_UITHREADDLG);
                  m_dlg.ShowWindow(SW_SHOW);
                  m_pMainWnd=&m_dlg;
                  return TRUE;
                  }
                  int CUIThread::ExitInstance()
                  {
                  m_dlg.DestroyWindow();
                  return CWinThread::ExitInstance();
                  }
                  
            7. 雙擊按鈕IDC_UI_THREAD,添加消息響應函數(shù):
              void CMultiThread6Dlg::OnUiThread()
                  {
                  CWinThread *pThread=AfxBeginThread(RUNTIME_CLASS(CUIThread));
                  }
                  
              并在MultiThread6Dlg.cpp的開頭添加:
              #include "UIThread.h"
                  

              好了,編譯并運行程序吧。每單擊一次“用戶界面線程”按鈕,都會彈出一個線程對話框,在任何一個線程對話框內(nèi)按下鼠標左鍵,都會彈出一個消息框。

            posted on 2011-04-25 15:33 厚積薄發(fā) 閱讀(276) 評論(0)  編輯 收藏 引用 所屬分類: Windows編程

            導航

            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            統(tǒng)計

            常用鏈接

            留言簿

            隨筆分類

            文章分類

            文章檔案

            搜索

            最新評論

            亚洲美日韩Av中文字幕无码久久久妻妇| 国产精品久久久久9999高清| 狠狠精品久久久无码中文字幕 | 嫩草伊人久久精品少妇AV| 亚洲愉拍99热成人精品热久久 | 久久久久夜夜夜精品国产| 国产巨作麻豆欧美亚洲综合久久| 亚洲国产成人久久一区WWW| 久久青青草原精品国产| 久久精品国产第一区二区| 日日躁夜夜躁狠狠久久AV| 久久99久久成人免费播放| 人妻久久久一区二区三区| 久久久久久青草大香综合精品| 中文无码久久精品| 久久一区二区免费播放| 久久精品亚洲日本波多野结衣| 日批日出水久久亚洲精品tv| av午夜福利一片免费看久久| 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区 | 亚洲va中文字幕无码久久| 国产A级毛片久久久精品毛片| 亚洲中文字幕无码久久2020| 久久无码人妻精品一区二区三区 | 久久久久久免费一区二区三区| 久久久久久久久波多野高潮| 国产亚洲成人久久| 国产精品日韩欧美久久综合| 国产午夜免费高清久久影院| 伊人色综合久久天天人手人婷| 国产精品久久婷婷六月丁香| 久久国产香蕉一区精品| 色综合久久最新中文字幕| 久久九九全国免费| 久久精品人人做人人爽电影| 国产精品视频久久| 久久九九有精品国产23百花影院| 精品久久久久久久无码| 久久国产精品久久国产精品| 中文字幕成人精品久久不卡| 国产A级毛片久久久精品毛片|