MFC多線程CWinThread執行個體

來源:互聯網
上載者:User

執行個體嘛,就不多做太多說明了。這裡不說worker線程的使用,那種掛回調的東西,不說了。而且幾乎不可控的。這裡只說派生CWinThread方式。這裡基於對話方塊工程給出執行個體。

1、派生CWinThread,不要自己寫代碼了,直接,類別檢視--右鍵add class -- mfc class -- base class設定為CWinThread。

2、添加訊息處理,得到的完整的類代碼如下:

#pragma once#define WM_TEST  WM_USER + 105// MyThreadclass MyThread : public CWinThread{DECLARE_DYNCREATE(MyThread)protected:MyThread();           // protected constructor used by dynamic creationvirtual ~MyThread();public:virtual BOOL InitInstance();virtual int ExitInstance();    void    OnTest(WPARAM wParam, LPARAM lParam);protected:DECLARE_MESSAGE_MAP()};// MyThread.cpp : implementation file//#include "stdafx.h"#include "ThreadDlg.h"#include "MyThread.h"// MyThreadIMPLEMENT_DYNCREATE(MyThread, CWinThread)MyThread::MyThread(){}MyThread::~MyThread(){}BOOL MyThread::InitInstance(){// TODO:  perform and per-thread initialization herereturn TRUE;}int MyThread::ExitInstance(){// TODO:  perform any per-thread cleanup herereturn CWinThread::ExitInstance();}void MyThread::OnTest(WPARAM wParam,LPARAM lParam){        AfxMessageBox("test");}BEGIN_MESSAGE_MAP(MyThread, CWinThread)    ON_THREAD_MESSAGE(WM_TEST, OnTest)END_MESSAGE_MAP()// MyThread message handlers

 

3、對話方塊類如下,添加了多線程成員指標:

class CThreadDlgDlg : public CDialogEx{private:    MyThread *myThr;

4、修改函數CThreadDlgDlg::OnInitDialog():

BOOL CThreadDlgDlg::OnInitDialog(){CDialogEx::OnInitDialog();// 將“關於...”功能表項目添加到系統功能表中。// IDM_ABOUTBOX 必須在系統命令範圍內。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);ASSERT(bNameValid);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 設定此對話方塊的表徵圖。當應用程式主視窗不是對話方塊時,架構將自動//  執行此操作SetIcon(m_hIcon, TRUE);// 設定大表徵圖SetIcon(m_hIcon, FALSE);// 設定小表徵圖// TODO: 在此添加額外的初始化代碼    myThr = (MyThread *)AfxBeginThread(RUNTIME_CLASS(MyThread));return TRUE;  // 除非將焦點設定到控制項,否則返回 TRUE}

5、對話方塊添加一個按鈕,實現點擊事件函數:

void CThreadDlgDlg::OnBnClickedButton1(){    // TODO: Add your control notification handler code here    myThr->PostThreadMessage(WM_TEST, 0, 0);}

每次點擊按鈕,就會出發多線程的test函數了。

6、要線程退出怎麼辦?對於worker線程,就是一個回調這種,沒有多大問題,要麼用

void CThreadDlgDlg::OnBnClickedButton1(){    // TODO: Add your control notification handler code here    myThr->PostThreadMessage(WM_QUIT, 0, 0);}

7、線程間通訊,同步互斥,以worker線程為例子,在dlg類裡面添加一個CSemaphore成員,然後在建構函式裡面初始化為0,先看一下CSemaphore的建構函式:

CSemaphore(   LONG lInitialCount = 1,   LONG lMaxCount = 1,   LPCTSTR pstrName = NULL,   LPSECURITY_ATTRIBUTES lpsaAttributes = NULL );

下面列出完整原始碼:

// CDlgOncloseDlg dialogclass CDlgOncloseDlg : public CDialogEx{    // Constructionpublic:    CDlgOncloseDlg(CWnd* pParent = NULL);// standard constructor    // Dialog Data    enum { IDD = IDD_DLGONCLOSE_DIALOG };protected:    virtual void DoDataExchange(CDataExchange* pDX);// DDX/DDV support    // Implementationprotected:    HICON m_hIcon;    // Generated message map functions    virtual BOOL OnInitDialog();    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);    afx_msg void OnPaint();    afx_msg HCURSOR OnQueryDragIcon();    DECLARE_MESSAGE_MAP()public:    afx_msg void OnBnClickedButtonNewThr();private:    CWinThread *WorkThr;    CSemaphore mySem;public:    afx_msg void OnBnClickedButtonNewThr2();};CDlgOncloseDlg::CDlgOncloseDlg(CWnd* pParent /*=NULL*/)    : CDialogEx(CDlgOncloseDlg::IDD, pParent),    mySem(0){    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);}void CDlgOncloseDlg::DoDataExchange(CDataExchange* pDX){    CDialogEx::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(CDlgOncloseDlg, CDialogEx)    ON_WM_SYSCOMMAND()    ON_WM_PAINT()    ON_WM_QUERYDRAGICON()    ON_BN_CLICKED(IDC_BUTTON_NEW_THR, &CDlgOncloseDlg::OnBnClickedButtonNewThr)    ON_BN_CLICKED(IDC_BUTTON_NEW_THR2, &CDlgOncloseDlg::OnBnClickedButtonNewThr2)END_MESSAGE_MAP()UINT myThread(LPVOID pParam){    CSemaphore *mySem;    if(!pParam)    {        return -1;    }    else    {        mySem = (CSemaphore *)pParam;    }    while(1)    {        mySem->Lock();        TRACE("myThread\n");    }    return 0;}void CDlgOncloseDlg::OnBnClickedButtonNewThr(){    // TODO: Add your control notification handler code here    WorkThr = AfxBeginThread(myThread, (LPVOID)&mySem);}void CDlgOncloseDlg::OnBnClickedButtonNewThr2(){    // TODO: Add your control notification handler code here    TRACE("OnBnClickedButtonNewThr2\n");    mySem.Unlock();}

當然,Worker線程最大的作用就是,讓它做一些複雜的事情,把主線程釋放出來,這裡做一個worker,然後主線程等worker完成:

UINT ReadFile(LPVOID in){    CSemaphore *inSem = (CSemaphore *)in;    if(!in)    {        return 0;    }    for(int i = 1000000000; i > 0; i--)        ;    inSem->Unlock();    return 0;}void CMFCApplication1View::OnFileOpen(){    if(!dlg )    {        dlg = new CtestDlg;        dlg->Create(this);        dlg->ModifyStyleEx(0, WS_EX_TOPMOST);    }    dlg->ShowWindow(SW_SHOW);    AfxBeginThread(ReadFile, &sem);    sem.Lock();    dlg->DestroyWindow();    delete dlg;    dlg = NULL;}

 

8、UI線程,建立對話方塊:

添加對話方塊,添加相應的類為ThrTestDlg,新增成員函數CreateDlg()用於非模態對話方塊建立時候使用,這裡列出完整類定義:

class ThrTestDlg : public CDialogEx{    DECLARE_DYNAMIC(ThrTestDlg)public:    BOOL CreateDlg()    {        return CDialogEx::Create(IDD);    }public:    ThrTestDlg(CWnd* pParent = NULL);   // standard constructor    virtual ~ThrTestDlg();    // Dialog Data    enum { IDD = IDD_DIALOG1 };protected:    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support    DECLARE_MESSAGE_MAP()};

然後,修改UI線程類定義,在init和exit函數裡面,實現建立和銷毀對話方塊:

class CMyThread : public CWinThread{DECLARE_DYNCREATE(CMyThread)protected:CMyThread();           // protected constructor used by dynamic creationvirtual ~CMyThread();public:virtual BOOL InitInstance();virtual int ExitInstance();    void end()    {        this->PostThreadMessage(WM_QUIT, 0, 0);    }    ThrTestDlg *dlg;protected:DECLARE_MESSAGE_MAP()};// CMyThreadIMPLEMENT_DYNCREATE(CMyThread, CWinThread)CMyThread::CMyThread(){    dlg = new ThrTestDlg();}CMyThread::~CMyThread(){    delete dlg;}BOOL CMyThread::InitInstance(){// TODO:  perform and per-thread initialization here    dlg->CreateDlg();    dlg->ModifyStyleEx(0, WS_EX_TOPMOST);    dlg->ShowWindow(SW_SHOW);return TRUE;}int CMyThread::ExitInstance(){// TODO:  perform any per-thread cleanup here    dlg->DestroyWindow();return CWinThread::ExitInstance();}BEGIN_MESSAGE_MAP(CMyThread, CWinThread)END_MESSAGE_MAP()

再修改工程的對話方塊,添加兩個按鈕事件,一個做建立新線程,一個退出前者建立的線程。代碼如下:

void CDlgOncloseDlg::OnBnClickedButtonNewThr(){    // TODO: Add your control notification handler code here    WorkThr = AfxBeginThread(RUNTIME_CLASS(CMyThread));}void CDlgOncloseDlg::OnBnClickedButtonNewThr2(){    // TODO: Add your control notification handler code here    TRACE("OnBnClickedButtonNewThr2\n");    WorkThr->PostThreadMessageW(WM_QUIT, 0, 0);    //mySem.Unlock();}
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.