非同期タスク キューの設計

このトピックでは、Microsoft Game Development Kit (GDK) の非同期設計パターンと共に使用する Microsoft Game Development Kit (GDK) タスク キューについて説明します。 タスク キューは、処理および完了タスクのコールバックをキューに入れるための API です。 いずれかのディスパッチ モードでタスク キューを構成できます。たとえば、ゲームのワークロードを慎重に管理する際に使用できる手動ディスパッチ メカニズムが挙げられます。

タスク キュー API の概要

タスク キューは、処理ポートと完了ポートの 2 つのキュー ポートで構成されます。 処理ポートは非同期作業を行うため、完了ポートはそれについてユーザーに連絡するために使用され、これら両方のポートは頻繁に必要になります。そのため、これらは同じオブジェクトにまとめられています。

タスク キューの説明を次に示します。

  • 2 つのタスク キュー ポートが含まれます。

  • タスク キュー ポートごとにディスパッチ モードを割り当てることができます。ディスパッチ モードにより、キューの中の項目がどのようにディスパッチされるかが決まります。

  • ディスパッチ モードには、システム スレッド プールを介した完全自動ディスパッチから、タスクを明示的に削除しなければならない完全手動ディスパッチまで、さまざまな種類があります。

  • コールバックは、キューのいずれかのポートに送信することができます。

  • キューは、ハンドルとして表されます。 ハンドルは複製できるので、キューの参照カウントを増やすことができます。

タスク キュー ポートを個別にディスパッチ モードを指定して構成することができます。 ディスパッチ モードにより、ポートのキューに入ったコールバックがどのように処理されるのかが決まります。 ディスパッチ モードにはいくつかの種類があります。

  • スレッド プール: スレッド プール キューに入れられたコールバックは、システム スレッド プールで実行されます。 スレッド プールは、スレッド プールのスレッドが利用可能になると、実行する呼び出しをキューから順番に受け取り、複数の呼び出しを並行で実行します。

  • シリアル化スレッド プール: コールバックはキューに入れられ、スレッド プールで実行されますが、すべてのスレッド プール スレッドで並行して実行されるのではなく、順番に実行されます。

  • 手動: 手動キューに置かれたコールバックは、自動的にはディスパッチされません。 デベロッパー側で、目的のスレッドにそれらをディスパッチする必要があります。 手動タスク キューを使用している場合、Windows メッセージ キューもポンプする必要があります。

  • 即時: 即時ディスパッチ モードでは、コールバックはキューに入りません。 コールバックを送信したスレッドで呼び出しが直ちに実行されます。

タスク キュー ハンドルは、共有可能なリソースです。 ハンドルを閉じると、キューの参照が解放されます。 キューは、すべての参照が解放されるまで実際には破棄されません。 XTaskQueueDuplicateHandleXTaskQueueSubmitCallbackXTaskQueueSubmitDelayedCallbackXTaskQueueCreateComposite はすべて、キュー ハンドルへの参照を追加します。 これは、すべてのコールバックが完了するまで、キューが実際には破棄されないことを意味します。

タスク キュー ハンドルはプロセスごとのリソースであり、プロセスの外部で、マーシャリングすることや使用することはできません。

使用パターン

タスク キューの一般的な使用パターンの例を次に示します。

  1. タスク キュー ハンドルを作成し、各ポートのディスパッチ モードを指定します。

  2. 手動ディスパッチを使用する場合は、キューのディスパッチ関数を呼び出すためにアプリ固有のスレッドを確立します。

  3. Microsoft Game Development Kit (GDK) 呼び出しへのパラメーターとしてキューを使用するか、XTaskQueueCallback を使用して直接提出します。

  4. アプリをシャットダウンするとき、タスク キューを終了することもできます。

非同期タスク キューの使用方法のトピック

このセクションでは、一般的な非同期タスク キュー シナリオでの使用方法の例を示します。

このセクションの内容

スレッド プール タスク キューを作成する
システム スレッド プールで処理コールバックと完了コールバックの両方をディスパッチするタスク キューを作成する方法を例で示します。

コールバックの送信
タスク キューの処理ポートまたは完了ポートにコールバックが送信される方法の例を示します。

タスク キュー ハンドルを複製する
タスクキューハンドルを複製する方法を示す例を提供します。 実行時間の長い処理がある場合、処理の間、タスク キュー ハンドルを複製したいことがあります。 このようにして、XTaskQueueCloseHandle を呼び出しても、必要な間はキューを閉じません。

手動タスク キューを作成する
この例では、手動でポンプされるタスク キューを作成する方法を示しています。 作業ポートと完了ポート両方の呼び出しをディスパッチする 2 つの STL スレッドを作成します。

手動キューのディスパッチを管理するためにイベントを使用する
この例では、タスク キューを使用して、ディスパッチする項目がある場合に条件変数を通知する方法を示します。

Windows メッセージ ループでのタスク キューの使用
処理のためにスレッド プールを使用しますが、完了ポート コールバックを Win32 ウィンドウ プロシージャに統合する例を提供します。 また、この例は、別のスレッド モデルに統合する際に、タスク キューを適切に終了する方法も示します。

プロセス タスク キューの使用
プロセス タスク キューの使用方法を示す例を提供します。 既定のプロセス タスク キューは、処理と完了両方のディスパッチでスレッド プールを使用します。

複合タスク キューを作成する
処理のためにスレッド プールを使用しますが、完了ポート コールバックを Win32 WindowProc コールバック関数に統合するサンプルを提供します。 また、このサンプルでは別のスレッド モデルに統合する際に、タスク キューを適切に終了する方法も示します。

遅延コールバックの使用
500 ミリ秒ごとに 10 回のコールバックを呼び出す、遅延コールバックの使用方法を示す例を示します。 タスク キューを使用して、XTaskQueueSubmitDelayedCallback API を使用して将来コールバックを送信します。 この機能を使用して、失敗したコールをわずかな時間をおいて再試行できるほか、定期的なイベント用の低コストのタイマーとすることもできます。

タスク キュー待機処理の使用
タスク キュー待機処理の使用方法を示す例を提供します。 タスク キューに Win32 カーネル ハンドルを登録できます。 ハンドルが通知されると、コールバックがキューに送信されます。

関連項目

System

非同期プログラミング モデル

XTaskQueue