none
複数のスレッドを同時に起動する方法はないでしょうか RRS feed

  • 質問

  • おつかれさまです。

    意図的にI/Oの滞留に近い状態を作りたく、複数作成したスレッドを、1つのオブジェクトで同時に起動するよい方法は何かないでしょうか?

    イメージ的にはWaitForSingleObject(では出来ないとは思いますが)でシグナル待ちしているスレッドを複数作成し、1つのオブジェクトでイベント待ちしている全てのスレッドを同時起動するようなことを考えております。

    言語はC/C++になります。

    いいお知恵を拝借したく、よろしくお願いいたします。

    2018年7月9日 8:53

回答

  • イメージ的にはWaitForSingleObject(では出来ないとは思いますが)でシグナル待ちしているスレッドを複数作成し、1つのオブジェクトでイベント待ちしている全てのスレッドを同時起動するようなことを考えております。

    間違っていましたらすみません。複数スレッド処理の初めで WaitForSingleObject 関数で指定オブジェクトがシグナル状態になるのを待つのでは駄目なのでしょうか?例えば下記のコードのように

    #include <windows.h>
    
    HANDLE hEvent;
    
    DWORD WINAPI ThreadFunc1(LPVOID p)
    {
    	WaitForSingleObject(hEvent, INFINITE);
    
    	OutputDebugString(TEXT("1\r\n"));
    
    	PostMessage((HWND)p, WM_APP + 1, 0, 0);
    
    	ExitThread(0);
    }
    
    DWORD WINAPI ThreadFunc2(LPVOID p)
    {
    	WaitForSingleObject(hEvent, INFINITE);
    
    	OutputDebugString(TEXT("2\r\n"));
    
    	PostMessage((HWND)p, WM_APP + 2, 0, 0);
    
    	ExitThread(0);
    }
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	static HANDLE hThread1;
    	static HANDLE hThread2;
    	switch (msg)
    	{
    	case WM_CREATE:
    		CreateWindow(TEXT("BUTTON"), TEXT("複数スレッド起動"), WS_VISIBLE | WS_CHILD, 10, 10, 256, 32, hWnd, (HMENU)IDOK, ((LPCREATESTRUCT)lParam)->hInstance, 0);
    		break;
    	case WM_COMMAND:
    		if (LOWORD(wParam) == IDOK)
    		{
    			if (hEvent)
    			{
    				CloseHandle(hEvent);
    				hEvent = 0;
    			}
    
    			hEvent = CreateEvent(NULL, TRUE, FALSE, TEXT("TEST"));
    
    			DWORD dwParam;
    			hThread1 = CreateThread(0, 0, ThreadFunc1, (LPVOID)hWnd, 0, &dwParam);
    			hThread2 = CreateThread(0, 0, ThreadFunc2, (LPVOID)hWnd, 0, &dwParam);
    
    			Sleep(1000);
    
    			SetEvent(hEvent); // 同時実行
    		}
    		break;
    	case WM_APP + 1:
    		if (hThread1)
    		{
    			WaitForSingleObject(hThread1, INFINITE);
    			CloseHandle(hThread1);
    			hThread1 = 0;
    		}
    		break;
    	case WM_APP + 2:
    		if (hThread2)
    		{
    			WaitForSingleObject(hThread2, INFINITE);
    			CloseHandle(hThread2);
    			hThread2 = 0;
    		}
    		break;
    	case WM_DESTROY:
    		if (hEvent)
    		{
    			CloseHandle(hEvent);
    			hEvent = 0;
    		}
    		PostQuitMessage(0);
    		break;
    	default:
    		return DefWindowProc(hWnd, msg, wParam, lParam);
    	}
    	return 0;
    }
    
    // WinMain は省略
    • 編集済み kenjinoteMVP 2018年7月9日 9:38
    • 回答としてマーク mt 2018年7月9日 23:22
    2018年7月9日 9:34

すべての返信

  • イメージ的にはWaitForSingleObject(では出来ないとは思いますが)でシグナル待ちしているスレッドを複数作成し、1つのオブジェクトでイベント待ちしている全てのスレッドを同時起動するようなことを考えております。

    間違っていましたらすみません。複数スレッド処理の初めで WaitForSingleObject 関数で指定オブジェクトがシグナル状態になるのを待つのでは駄目なのでしょうか?例えば下記のコードのように

    #include <windows.h>
    
    HANDLE hEvent;
    
    DWORD WINAPI ThreadFunc1(LPVOID p)
    {
    	WaitForSingleObject(hEvent, INFINITE);
    
    	OutputDebugString(TEXT("1\r\n"));
    
    	PostMessage((HWND)p, WM_APP + 1, 0, 0);
    
    	ExitThread(0);
    }
    
    DWORD WINAPI ThreadFunc2(LPVOID p)
    {
    	WaitForSingleObject(hEvent, INFINITE);
    
    	OutputDebugString(TEXT("2\r\n"));
    
    	PostMessage((HWND)p, WM_APP + 2, 0, 0);
    
    	ExitThread(0);
    }
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	static HANDLE hThread1;
    	static HANDLE hThread2;
    	switch (msg)
    	{
    	case WM_CREATE:
    		CreateWindow(TEXT("BUTTON"), TEXT("複数スレッド起動"), WS_VISIBLE | WS_CHILD, 10, 10, 256, 32, hWnd, (HMENU)IDOK, ((LPCREATESTRUCT)lParam)->hInstance, 0);
    		break;
    	case WM_COMMAND:
    		if (LOWORD(wParam) == IDOK)
    		{
    			if (hEvent)
    			{
    				CloseHandle(hEvent);
    				hEvent = 0;
    			}
    
    			hEvent = CreateEvent(NULL, TRUE, FALSE, TEXT("TEST"));
    
    			DWORD dwParam;
    			hThread1 = CreateThread(0, 0, ThreadFunc1, (LPVOID)hWnd, 0, &dwParam);
    			hThread2 = CreateThread(0, 0, ThreadFunc2, (LPVOID)hWnd, 0, &dwParam);
    
    			Sleep(1000);
    
    			SetEvent(hEvent); // 同時実行
    		}
    		break;
    	case WM_APP + 1:
    		if (hThread1)
    		{
    			WaitForSingleObject(hThread1, INFINITE);
    			CloseHandle(hThread1);
    			hThread1 = 0;
    		}
    		break;
    	case WM_APP + 2:
    		if (hThread2)
    		{
    			WaitForSingleObject(hThread2, INFINITE);
    			CloseHandle(hThread2);
    			hThread2 = 0;
    		}
    		break;
    	case WM_DESTROY:
    		if (hEvent)
    		{
    			CloseHandle(hEvent);
    			hEvent = 0;
    		}
    		PostQuitMessage(0);
    		break;
    	default:
    		return DefWindowProc(hWnd, msg, wParam, lParam);
    	}
    	return 0;
    }
    
    // WinMain は省略
    • 編集済み kenjinoteMVP 2018年7月9日 9:38
    • 回答としてマーク mt 2018年7月9日 23:22
    2018年7月9日 9:34
  • 補足すると、CreateEvent()の第2引数bManualResetをtrueに設定すると、ResetEvent()を呼ぶまでシグナル状態を維持するため、そのタイミングで待ち受けていたWaitForSingleObject系は全て処理を継続できます。
    逆にbManualResetをfalseに設定すると、ある1スレッドのWaitForSingleObject系だけが処理を継続し、残りのスレッドは待機し続けます。

    この機能を使うことで、質問文「複数作成したスレッドを、1つのオブジェクトで同時に起動する」を実現できます。

    2018年7月9日 13:43
  • 解説までいただき、ありがとうございます。

    いただいた情報で試してみます。

    > 逆にbManualResetをfalseに設定すると、ある1スレッドのWaitForSingleObject系だけが処理を継続し、残りのスレッドは待機し続けます。

    ここの部分を勘違いしていたようで、1つのMutexオブジェクトに対してWaitForSingleObjectが待機状態から復帰できるのは1スレッドのみだと思い込んでおりました。

    2018年7月9日 23:22