LoginSignup
6
7

More than 1 year has passed since last update.

[C++] C++でマルチスレッドする

Last updated at Posted at 2021-04-22

もくじ

やりたいこと

最近のC++では、マルチスレッドで処理を行うときに、処理の中身をラムダ式で書けたりするらしい。試したい。

サンプルプログラム

#include <thread>
#include "framework.h"
#include "WindowsProject1.h"
#include "resource.h"

// グローバル変数:
HINSTANCE hInst;                                // 現在のインターフェイス

// このコード モジュールに含まれる関数の宣言を転送します:
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    hInst = hInstance;

    DialogBox(hInst, L"MyTestDlgBase_Main", NULL, (DLGPROC)MyDlgProc);

    return (int)0;
}

// スレッド終了フラグ
int threadStop = !0;

// スレッドAの処理
void ThreadA()
{
    OutputDebugString(L"+ スレッドA開始\r\n");

    while (!threadStop)
    {
        OutputDebugString(L"  スレッドA実行中...\r\n");
        Sleep(500);
    }

    OutputDebugString(L"- スレッドA終了\r\n");
}


// 参考
// スレッド終了時にはjoin()で待たないといけないのはここを見て気づいた
// https://qiita.com/kaoru/items/7de0399b11f83241687c
// ラムダでの書き方
// https://qiita.com/termoshtt/items/d3cb7fe226cdd498d2ef
BOOL CALLBACK MyDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
{
    static std::thread th_a;
    static std::thread th_b;

    switch (msg) {
    case WM_COMMAND:
        switch (LOWORD(wp)) {
        case IDOK:
            EndDialog(hDlg, IDOK);
            return TRUE;
        case IDCANCEL:
            EndDialog(hDlg, IDCANCEL);
            return TRUE;

        case IDC_BUTTON1:
            if (threadStop != 0)
            {
                // スレッドA,Bの終了フラグをクリア
                threadStop = 0;

                // スレッドA開始
                th_a = std::thread(ThreadA);

                // スレッドB開始
                int param = 0;
                th_b = std::thread([&param]{
                            OutputDebugString(L"+ スレッドB開始\r\n");

                            while (!threadStop)
                            {
                                OutputDebugString(L"  スレッドB実行中...\r\n");
                                Sleep(1000);
                            }

                            OutputDebugString(L"- スレッドB終了\r\n");
                        });
            }
            else
            {
                // スレッドA,Bの終了フラグをON(スレッドを終わらせる)
                threadStop = !0;

                // スレッド終了時にはjoinで終わるのを待たないと、異常終了してしまう(Abort)
                th_a.join();
                th_b.join();
            }
            break;
        }
        return FALSE;

    case WM_CLOSE:
        threadStop = !0;
        th_a.join();
        th_b.join();
        break;
    }
    return FALSE;
}

引っかかった点

スレッドが終わりきってないときにexeが終了すると、エラーが起きてしまう。

なので、スレッドが終わるまで待ってからプログラム終了するようにする。
スレッドが終わるのをまつため、th_a.join();を使ってスレッドが終わるまで待つ。

std::thread th_a = std::thread(ThreadA);と書くと、その時点からスレッドが走り出す

std::threadのobjectだけ先に作っておいて、後で好きな時にstartさせたかったが、std::thread th_a = std::thread(ThreadA);とかくと、その時点からすぐにスレッドが走り出してしまう。

まずはstd::thread th_a;で宣言だけしておいて、スタートさせたいところでth_a = std::thread(ThreadA);をすればOK。

6
7
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7