Win32API 新しいスレッドプール

Windows Vistaで追加されたスレッドプールの特徴のひとつとして、従来のQueueUserWorkItem関数ではコールバック関数が終了したことを、スレッド起動側が知ることができなかったのが、新しいスレッドプールでは、コールバック関数の終了を知ることができるようになった、ということがある。


新しいスレッドプールの使い方の手順としたは、おおよそ以下のようになる。

1.CreateThreadpoolWork関数で、スレッドプールの作業アイテムを作成

2.SubmitThreadpoolWork関数で、作業アイテムを割り当てる

3.WaitForThreadpoolWorkCallbacks関数で、作業アイテムの完了を待機する

4.CloseThreadpoolWork関数で、作業アイテムを解放する





CreateThreadpoolWork関数のプロトタイプ

PTP_WORK WINAPI CreateThreadpoolWork(
  _In_         PTP_WORK_CALLBACK pfnwk,
  _Inout_opt_  PVOID pv,
  _In_opt_     PTP_CALLBACK_ENVIRON pcbe
);


WorkCallback関数のプロトタイプ

VOID CALLBACK WorkCallback(
  _Inout_      PTP_CALLBACK_INSTANCE Instance,
  _Inout_opt_  PVOID Context,
  _Inout_      PTP_WORK Work
);


SubmitThreadpoolWork関数のプロトタイプ

VOID WINAPI SubmitThreadpoolWork(
  _Inout_  PTP_WORK pwk
);


WaitForThreadpoolWorkCallbacksのプロトタイプ

VOID WINAPI WaitForThreadpoolWorkCallbacks(
  _Inout_  PTP_WORK pwk,
  _In_     BOOL fCancelPendingCallbacks
);


作業アイテムを解放する
CloseThreadpoolWorkのプロトタイプ

VOID WINAPI CloseThreadpoolWork(
  _Inout_  PTP_WORK pwk
);



新しいスレッドプールを用いた、簡単な例を以下に示す。
コールバック関数の中で、クリティカルセクションを用いて同期処理を行なっている。

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

PTP_WORK g_pWorkItem;
int g_nCounter = 0;
CRITICAL_SECTION g_Crit;

void NTAPI WorkCallback(PTP_CALLBACK_INSTANCE Instance, PVOID Context, PTP_WORK Work)
{
    for (int i = 0; i < 100; i++) {
        EnterCriticalSection(&g_Crit);
        printf("%d\n", ++g_nCounter);
        Sleep(1);
        LeaveCriticalSection(&g_Crit);
    }
}

int main()
{
    //クリティカルセクション初期化
    InitializeCriticalSection(&g_Crit);

    //スレッドプールの作業アイテムを作成
    g_pWorkItem = ::CreateThreadpoolWork(WorkCallback, NULL, NULL);

    for (int i = 0; i < 100; i++) {
        //作業アイテムの割り当て
        SubmitThreadpoolWork(g_pWorkItem);
    }

    //待ち行列に入っている作業アイテムの処理が完了するのを待機する
    //(第二引数にFALSEを指定した場合は、待ち行列にある作業アイテムを
    //キャンセルする。)
    WaitForThreadpoolWorkCallbacks(g_pWorkItem, FALSE);

    //作業アイテムを解放する
    CloseThreadpoolWork(g_pWorkItem);

    //クリティカルを破棄
    DeleteCriticalSection(&g_Crit);

    return 0;
}






参考

CreateThreadpoolWorkhttp://msdn.microsoft.com/ja-jp/library/windows/desktop/ms682478(v=vs.85).aspx
WorkCallbackhttp://msdn.microsoft.com/ja-jp/library/windows/desktop/ms687396(v=vs.85).aspx
SubmitThreadpoolWorkhttp://msdn.microsoft.com/ja-jp/library/windows/desktop/ms686338(v=vs.85).aspx
WaitForThreadpoolWorkCallbackshttp://msdn.microsoft.com/ja-jp/library/windows/desktop/ms687053(v=vs.85).aspx
CloseThreadpoolWorkhttp://msdn.microsoft.com/ja-jp/library/windows/desktop/ms682043(v=vs.85).aspx