【VC++】簡単なマルチスレッド その1

0

    <機能>

    (1)AfxBeginThreadを使用したマルチスレッドサンプルです

    (2)マルチスレッドでカウントアップ処理を行います

    (3)バックグラウンドプログラムの中断、再開ができます

     中断:ResumeThread

     再開:SuspendThread

    (4)バックグラウンド処理が終了を通知します

    (5)ダイアログは終了通知を受け取り終了処理をします

     

    <イメージ>

    スレッド開始 ボタン押下によりカウントアップを開始

    スレッド開始イメージ,AfxBeginThread

    中断 ボタン押下により中断します(中断→再開に変更)

    中断ボタンを再開ボタンに変更,AfxBeginThread

    処理が終了したらユーザ定義メッセージで通知します

    終了メッセージ,AfxBeginThread

     

    <動作検証&開発環境>
    Visual Studio Community 2017

     

    <使い方>

    1.ダイアログベースでThreadSampleプロジェクトを作成

    2.エディットボックスとボタンを配置

    IDC_EDIT : ReadOnly=TRUE

    3.コントロール変数を追加

    IDC_EDIT : m_EdtCount(種類EDIT/カテゴリControl)

    IDC_BTNST : m_BtnStart(種類BUTTON)

    IDC_BTNSTOP : m_BtnStop(種類BUTTON)

    IDOK : m_BtnOk(種類BUTTON)

    4.終了通知イベントハンドラ追加

    カスタムWindowsメッセージ : WM_MYMSG

    メッセージハンドラ名 : OnMyMsg

    5.ソースを追加

     

    ThreadSampleDlg.h

     

    class CThreadSampleDlg : public CDialogEx
    {

      //〜〜省略〜〜

    public:
        afx_msg void OnBnClickedOk();
        int count;
        CButton m_BtnStart;
        CButton m_BtnStop;
        CButton m_BtnOk;
        afx_msg void OnBnClickedBtnst();
        afx_msg void OnBnClickedBtnstop();
        CEdit m_EdtCount;
        CWinThread* mythread;
    protected:
        afx_msg LRESULT OnMyMsg(WPARAM wParam, LPARAM lParam);
    };

     

    ThreadSampleDlg.cpp

    //プロトタイプ宣言
    UINT __cdecl CountUpThread(LPVOID p);
    //ユーザ定義メッセージ
    #define WM_MYMSG (WM_USER + 100)
    CThreadSampleDlg::CThreadSampleDlg(CWnd* pParent /*=NULL*/)
        : CDialogEx(IDD_THREADSAMPLE_DIALOG, pParent)
    {
        m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    }
    void CThreadSampleDlg::DoDataExchange(CDataExchange* pDX)
    {
        CDialogEx::DoDataExchange(pDX);
        DDX_Control(pDX, IDC_BTNST, m_BtnStart);
        DDX_Control(pDX, IDC_BTNSTOP, m_BtnStop);
        DDX_Control(pDX, IDOK, m_BtnOk);
        DDX_Control(pDX, IDC_EDIT, m_EdtCount);
    }
    BEGIN_MESSAGE_MAP(CThreadSampleDlg, CDialogEx)
        ON_WM_SYSCOMMAND()
        ON_WM_PAINT()
        ON_WM_QUERYDRAGICON()
        ON_BN_CLICKED(IDOK, &CThreadSampleDlg::OnBnClickedOk)
        ON_BN_CLICKED(IDC_BTNST, &CThreadSampleDlg::OnBnClickedBtnst)
        ON_BN_CLICKED(IDC_BTNSTOP, &CThreadSampleDlg::OnBnClickedBtnstop)
        ON_MESSAGE(WM_MYMSG, &CThreadSampleDlg::OnMyMsg)
    END_MESSAGE_MAP()

    // CThreadSampleDlg メッセージ ハンドラー
    BOOL CThreadSampleDlg::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);
            }
            //バツボタン(「×」ボタン)を無効にする
            pSysMenu->EnableMenuItem(SC_CLOSE, MF_GRAYED);
        }
        // このダイアログのアイコンを設定します。アプリケーションのメイン ウィンドウがダイアログでない場合、
        //  Framework は、この設定を自動的に行います。
        SetIcon(m_hIcon, TRUE);            // 大きいアイコンの設定
        SetIcon(m_hIcon, FALSE);        // 小さいアイコンの設定
        //ボタンの初期状態
        m_BtnStart.EnableWindow(TRUE);
        m_BtnStop.EnableWindow(FALSE);
        m_BtnOk.EnableWindow(TRUE);
        m_BtnStop.SetWindowTextW(L"中 断");
        m_EdtCount.SetWindowTextW(L"0");
        return TRUE;  // フォーカスをコントロールに設定した場合を除き、TRUE を返します。
    }
    /*************************************************
    関数名 OnBnClickedOk
    機能   閉じる ボタン押下イベント
    *************************************************/

    void CThreadSampleDlg::OnBnClickedOk()
    {
        CDialogEx::OnOK();
    }
    /*************************************************
    関数名 OnBnClickedBtnst
    機能   スレッド開始 ボタン押下イベント
    *************************************************/

    void CThreadSampleDlg::OnBnClickedBtnst()
    {
        DWORD dwExitCode;
        MSG msg;
        //ボタンの状態をセット(中断のみ活性化)
        m_BtnStart.EnableWindow(FALSE);
        m_BtnStop.EnableWindow(TRUE);
        m_BtnOk.EnableWindow(FALSE);
        //カウントを初期化
        count = 0;
        //新しいスレッドを作成する
        //AfxBeginThreadについてはDeveloper Network参照
        mythread = AfxBeginThread(CountUpThread, this,0,0,NULL);
      
    }
    /*************************************************
    関数名 OnBnClickedBtnstop
    機能   中断 ボタン押下イベント
    *************************************************/

    void CThreadSampleDlg::OnBnClickedBtnstop()
    {
        CString cs;
        DWORD dwExitCode;
        //ボタンの状態をセット(中断のみ活性化)
        m_BtnStart.EnableWindow(FALSE);
        m_BtnStop.EnableWindow(TRUE);
        m_BtnOk.EnableWindow(FALSE);
        //ボタンのキャプションを取得
        m_BtnStop.GetWindowTextW(cs);
        if (cs == L"中 断") {
            m_BtnStop.SetWindowTextW(L"再 開");
            //スレッドを再開
            if (GetExitCodeThread(mythread->m_hThread, &dwExitCode)) {
                if (dwExitCode == STILL_ACTIVE) {
                    mythread->SuspendThread();
                }
            }
        }
        else {
            m_BtnStop.SetWindowTextW(L"中 断");
            //スレッドを中断
            if (GetExitCodeThread(mythread->m_hThread, &dwExitCode)) {
                if (dwExitCode == STILL_ACTIVE) {
                    mythread->ResumeThread();
                }
            }
        }
    }
    /*************************************************
    関数名 CountUpThread
    機能   ダイアログの変数をカウントアップして表示
    *************************************************/

    UINT __cdecl CountUpThread(LPVOID p) {
        CThreadSampleDlg* pDlg = (CThreadSampleDlg*)p;
        CString cs;
        while(1){
            //100までカウントアップ
            pDlg->count++;
            if (pDlg->count > 100) break;
            //ダイアログのエディットボックスに表示
            cs.Format(L"%d",pDlg->count);
            pDlg->m_EdtCount.SetWindowTextW(cs);
            Sleep(100);
        }
       
        ::SendMessage(pDlg->m_hWnd, WM_MYMSG, 0, 0);
        return 0;
    }
    /*************************************************
    関数名 OnMyMsg
    機能   ユーザ定義メッセージのイベントハンドラ
    *************************************************/

    afx_msg LRESULT CThreadSampleDlg::OnMyMsg(WPARAM wParam, LPARAM lParam)
    {
        AfxMessageBox(L"スレッドが終了しました", MB_ICONINFORMATION);
        //処理終了
        m_BtnStart.EnableWindow(TRUE);
        m_BtnStop.EnableWindow(FALSE);
        m_BtnOk.EnableWindow(TRUE);
       
        return 0;
    }

    よろしければポチッと押してください

    プログラマー ブログランキングへ

     



    calendar

    S M T W T F S
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
    << October 2017 >>

    profile

    others

    mobile

    qrcode