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

0

    <機能>

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

    (2)セマフォ(CSemaphoreクラス)を使って排他制御します

    (3)public変数 count を5スレッドからカウントアップします

     ※1スレッドあたり100カウントアップするためcount=500となります

     (排他制御(CSingleLock::Lock/Unlock)がないとcount<500)

     

    <イメージ>

    排他制御実装前の結果は、100カウントアップするスレッドを5つ起動してcount=500になりません

    CSemaphoreを使用しない結果

    セマフォを使ってcountをいずれか1スレッドからしか使えないように排他制御(CSingleLock::Lock/Unlock)するとcount=500となりました

    CSemaphoreを使用した結果

     

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

    <使い方>
    1.ダイアログベースでThreadSample2プロジェクトを作成
    2.エディットボックスとボタンを配置

     

    ダイアログにGUI配置
    IDC_EDIT1/IDC_EDIT2:ReadOnly=TRUE
    3.コントロール変数を追加
    エディットボックスにコントロース変数設定
    IDC_EDIT1 : m_EdtCount(種類EDIT/カテゴリControl)
    IDC_EDIT2 : m_EdtThread(種類EDIT/カテゴリControl)
    4.ソース追加

    ThreadSample2Dlg.h
    class CThreadSample2Dlg : public CDialogEx
    {
        //~~省略~~
    public:
        afx_msg void OnBnClickedButton1();
        int count;
        int threadno;
        CWinThread *mythread;
        CEdit m_EdtCount;
        CEdit m_EdtThread;
        //セマフォオブジェクト(スレッド間のロックに使用)
        CSemaphore m_cSmp;
    };
    ThreadSample2Dlg.cpp
    //プロトタイプ宣言
    UINT __cdecl CountUpThread(LPVOID p);
    BOOL CThreadSample2Dlg::OnInitDialog()
    {
        CDialogEx::OnInitDialog();
        // このダイアログのアイコンを設定します。アプリケーションのメイン ウィンドウがダイアログでない場合、
        //  Framework は、この設定を自動的に行います。
        SetIcon(m_hIcon, TRUE);            // 大きいアイコンの設定
        SetIcon(m_hIcon, FALSE);        // 小さいアイコンの設定
        //エディットボックスの初期表示
        m_EdtCount.SetWindowTextW(L"0");
        m_EdtThread.SetWindowTextW(L"0");
        return TRUE;
    }
    /*************************************************
    関数名 OnBnClickedButton1
    機能   セマフォで同期 ボタン押下イベント
    *************************************************/

    void CThreadSample2Dlg::OnBnClickedButton1()
    {
        MSG msg;
        count = 0;
        threadno = 0;
        //複数スレッド(5スレッド)起動
        for (int i = 0; i < 5; i++) {
            //スレッド番号(IDC_EDIT2に表示する)
            threadno = (i+1);
            TRACE(L"スレッド %d 起動¥n",threadno);
            AfxBeginThread(CountUpThread, this, 0, 0, NULL);
            while (PeekMessage(&msg, this->GetSafeHwnd(), 0, 0, PM_REMOVE)) {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            Sleep(300);
        }
    }
    /*************************************************
    関数名 CountUpThread
    機能   ダイアログの変数をカウントアップして表示
    *************************************************/

    UINT __cdecl CountUpThread(LPVOID p) {
       
        CThreadSample2Dlg* pDlg = (CThreadSample2Dlg*)p;
        CString cs;
        MSG msg;
        CSingleLock singlelock(&(pDlg->m_cSmp));
        //スレッド番号を更新
        cs.Format(L"%d", pDlg->threadno);
        pDlg->m_EdtThread.SetWindowTextW(cs);
        //1スレッドで100カウントアップする
        for(int i=0;i<100;i++){
           
            //複数スレッドからcountにアクセスする際に、いずれか1スレッドからしか
            //使用できないように排他制御する
            //CSingleLockについてはDeveloperNetWork参照

            singlelock.Lock();
            pDlg->count++;
            singlelock.Unlock();
            //ダイアログのエディットボックスに表示
            cs.Format(L"%d", pDlg->count);
            pDlg->m_EdtCount.SetWindowTextW(cs);
            while (PeekMessage(&msg, pDlg->GetSafeHwnd(), 0, 0, PM_REMOVE)) {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            TRACE(L"count = " + cs + L"¥n");
            Sleep(100);
        }
        return 0;
    }
     

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

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

     



    calendar

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

    profile

    others

    mobile

    qrcode