第101章 マルチスレッド その3


前章では、子スレッドの終了をWaitForSingleObject関数で待ちました。

今回は、複数の子スレッドが終了するのをWaitForMultipleObjects関数で待ちます。 複数の子スレッドが動作していると、全く不可思議なことが起ります。 それは、後に解決するとして、今回は複数のスレッドが終了するのを待つ方法についてのみ解説します。



DWORD WaitForMultipleObjects(
  DWORD nCount,             // ハンドルの数
  CONST HANDLE *lpHandles,  // オブジェクトハンドルの配列
  BOOL fWaitAll,            // 待機オプション
  DWORD dwMilliseconds      // タイムアウト時間
);
スレッドハンドルを配列に格納しておきます。

nCountには、ハンドルの数を指定します。
lpHandlesには、配列を指定します。
fWaitAllには、待機の方法を指定します。TRUEを指定すると配列内のすべてのオブジェクトがシグナル状態になるまで待機します。FALSEを指定すると、どれか一つがシグナル状態になるまで待ちます。
dwMillisecondsには、タイムアウト時間(ミリ秒)を指定します。INFINITEを指定すると、条件が満たされるまで待機します。

また、今回は子スレッドを3つ作りますが、全部できるまでスレッドはストップしていてもらいます。

これには、CreateThread関数の第5引数にCREATE_SUSPENDEDを指定します。

スレッドを再開するにはResumeThread関数を使います。

DWORD ResumeThread(
  HANDLE hThread   // スレッドハンドル
);
では、プログラムを見てみましょう。
/* mult04.c */

#include <stdio.h>
#include <windows.h>
#include <process.h>

unsigned __stdcall mythread0(void *);
unsigned __stdcall mythread1(void *);
unsigned __stdcall mythread2(void *);

int main()
{
    int i;
    HANDLE hTh[3];
    DWORD thID[3];

    hTh[0] = (HANDLE)_beginthreadex(
        NULL,
        0,
        mythread0,
        NULL,
        CREATE_SUSPENDED,
        &thID[0]
    );
    if (hTh[0] == 0) {
        printf("スレッド0作成失敗\n");
        return -1;
    }
    hTh[1] = (HANDLE)_beginthreadex(
        NULL,
        0,
        mythread1,
        NULL,
        CREATE_SUSPENDED,
        &thID[1]
    );
    if (hTh[1] == 0) {
        printf("スレッド1作成失敗\n");
        return -1;
    }
    hTh[2] = (HANDLE)_beginthreadex(
        NULL,
        0,
        mythread2,
        NULL,
        CREATE_SUSPENDED,
        &thID[2]
    );
    if (hTh[2] == 0) {
        printf("スレッド2作成失敗\n");
        return -1;
    }
    for (i = 0; i < 3; i++)
        ResumeThread(hTh[i]);

    for (i = 0; i < 10; i++)
        printf("Main [%d]\n", i);

    WaitForMultipleObjects(3, hTh, TRUE, INFINITE);

    for (i = 0; i < 3; i++)        
        CloseHandle(hTh[i]);

    return 0;
}

unsigned __stdcall mythread0(void *lpx)
{
    int i;
    for (i = 0; i < 10; i++)
        printf("子スレッド0[%d]\n", i);

    printf("子スレッド0終了!\n");

    return 0;
}

unsigned __stdcall mythread1(void *lpx)
{
    int i;
    for (i = 0; i < 20; i++)
        printf("子スレッド1[%d]\n", i);

    printf("子スレッド1終了!\n");

    return 0;
}

unsigned __stdcall mythread2(void *lpx)
{
    int i;
    for (i = 0; i < 5; i++)
        printf("子スレッド2[%d]\n", i);

    printf("子スレッド2終了!\n");

    return 0;
}
あまりにも長いので、最後の方の図です。

Mainスレッドは9まで、スレッド0は9まで、スレッド1は19まで表示されており、 その後プログラムが終了しています。複数のスレッドがきちんと終了するまで待機していることがわかります。



実行時の最初の方を見てみましょう。

何かおかしくありませんか。

Main[0]や、Main[1]が2回も表示されていますね。プログラム・ソースを見ても こんなことが起るとは予想できません。また、試行のたびに結果は異なります。




[Index][総合Index] [Previous Chapter] [Next Chapter]

Update May/26/2004 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。