<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    多線程編程之二 ---MFC中的多線程開發

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    下載源代碼

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

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

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

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

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

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

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

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

    六、MFC多線程編程實例

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

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

    用 MFC 類庫編程實現工作者線程

    例程5 MultiThread5

    為了與Win32 API對照,我們使用MFC 類庫編程實現例程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;
      };
      線程函數的聲明:
      UINT ThreadFunc(LPVOID lpParam);

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

      在類CMultiThread5Dlg內部添加protected型變量:

      CWinThread* pThread;
    4. 在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 類庫編程實現用戶界面線程

    創建用戶界面線程的步驟:

    1. 使用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()
      };
    2. 重載函數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函數中的任務而不執行消息循環,你可以通過這種方法,完成一個工作者線程的功能。

    例程6 MultiThread6

    1. 建立一個基于對話框的工程MultiThread6,在對話框IDD_MULTITHREAD6_DIALOG中加入一個按鈕IDC_UI_THREAD,標題為“用戶界面線程”
    2. 右擊工程并選中“New Class…”為工程添加基類為CWinThread派生線程類CUIThread。
    3. 給工程添加新對話框IDD_UITHREADDLG,標題為“線程對話框”。
    4. 為對話框IDD_UITHREADDLG創建一個基于CDialog的類CUIThreadDlg。使用ClassWizard為CUIThreadDlg類添加WM_LBUTTONDOWN消息的處理函數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()函數和ExitInstance()函數:
      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,添加消息響應函數:
      void CMultiThread6Dlg::OnUiThread() 
      {
      	CWinThread *pThread=AfxBeginThread(RUNTIME_CLASS(CUIThread));
      }
      并在MultiThread6Dlg.cpp的開頭添加:
      #include "UIThread.h"

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

    (未完待續)

    文章轉自:http://www.blogchinese.com/?uid-46225-action-viewspace-itemid-1244407

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全