コンテキスト
ここでは、同時実行ランタイムでのコンテキストの役割について説明します。 スケジューラにアタッチされるスレッドは、実行コンテキスト、または単にコンテキストと呼ばれます。 concurrency::wait の関数および concurrency::Context クラスは、コンテキストの動作を制御することができます。 指定した時間だけ現在のコンテキストを中断するには、wait 関数を使用します。 コンテキストをブロック、ブロック解除、および譲渡するタイミングをさらに制御する必要がある場合や、現在のコンテキストをオーバーサブスクライブする場合は、Context クラスを使用します。
ヒント
同時実行ランタイムには既定のスケジューラが備わっているため、アプリケーションでスケジューラを作成する必要はありません。タスク スケジューラではアプリケーションのパフォーマンスを微調整できるため、同時実行ランタイムを初めて使用する場合は、並列パターン ライブラリ (PPL) または非同期エージェント ライブラリから始めることをお勧めします。
wait 関数
concurrency::wait 関数は協調的に指定されたミリ秒数の現在のコンテキストの実行を開始します。 ランタイムは、譲渡された時間を使用して他のタスクを実行します。 指定した時間が経過すると、ランタイムは、コンテキストの実行を再スケジュールします。 したがって、wait 関数は、milliseconds パラメーターで指定した値よりも長く現在のコンテキストを中断させる場合があります。
milliseconds パラメーターとして 0 (ゼロ) を渡すと、ランタイムは、他のすべてのアクティブなコンテキストに処理を実行する機会が与えられるまで、現在のコンテキストを中断します。 これにより、他のすべてのアクティブ タスクに対してタスクを譲渡できます。
例
wait 関数を使用して現在のコンテキストを譲渡し、それにより他のコンテキストを実行できるようにする例については、「方法: スケジュール グループを使用して実行順序に影響を与える」を参照してください。
Context クラス
concurrency::Context クラスは、実行コンテキストの提供にプログラミング概念を 2 種類の重要な機能を提供し、T: 協調的にブロック機能もそのにブロック解除し、現在のコンテキストおよび機能を現在のコンテキストです。
協調ブロッキング
Context クラスを使用すると、現在の実行コンテキストをブロックまたは生成できます。 ブロックまたは譲渡する機能は、リソースを使用できないことが原因で現在のコンテキストを続行できない場合に有用です。
concurrency::Context::Block のメソッドは、現在のコンテキストをブロックします。 ブロックされたコンテキストは、その処理リソースを譲渡するため、ランタイムは他のタスクを実行できます。 concurrency::Context::Unblock のメソッドはブロックされているコンテキストをブロック解除します。 Context::Unblock メソッドは、Context::Block を呼び出したコンテキストとは異なるコンテキストから呼び出す必要があります。 ランタイムは、コンテキストがそれ自体のブロックを解除しようと concurrency::context_self_unblock をスローします。
コンテキストを協調的にブロックおよびブロック解除するには、通常、ポインターを取得し、現在のスレッドに関連付けられた、結果を呼び出します Context オブジェクトに格納するように concurrency::Context::CurrentContext を。 次に、Context::Block メソッドを呼び出して現在のコンテキストをブロックします。 その後、個別のコンテキストから Context::Unblock を呼び出して、ブロックされているコンテキストをブロック解除します。
Context::Block の呼び出しと Context::Unblock の呼び出しはペアとしてそれぞれ対応させる必要があります。 ランタイムは Context::Block または Context::Unblock のメソッドが他のメソッドに対応する BeginDelayAbort で連続的に呼び出されると concurrency::context_unblock_unbalanced をスローします。 ただし、Context::Unblock を呼び出す前に Context::Block を呼び出す必要はありません。 たとえば、あるコンテキストが Context::Unblock を呼び出し、その後別のコンテキストがその同じコンテキストに対し Context::Block を呼び出した場合、そのコンテキストはブロック解除されたままとなります。
concurrency::Context::Yield のメソッドは、ランタイムは他のタスクを実行し、コンテキストの実行を再スケジュールできるように実行を開始します。 Context::Block メソッドを呼び出した場合、ランタイムはコンテキストを再スケジュールしません。
例
Context::Block、Context::Unblock、および Context::Yield の各メソッドを使用して、協調セマフォ クラスを実装する例については、「方法: Context クラスを使用して協調セマフォを実装する」を参照してください。
オーバーサブスクリプション
既定のスケジューラは、使用できるハードウェア スレッドと同数のスレッドを作成します。 オーバーサブスクリプションを使用すると、所定のハードウェア スレッドに対し追加のスレッドを作成できます。
計算量が非常に多い処理の場合、オーバーサブスクリプションではオーバーヘッドが増えるため、通常は効率は向上されません。 ただし、ディスクやネットワーク接続からのデータの読み取りなど、待機時間が非常に長いタスクの場合、オーバーサブスクリプションにより一部のアプリケーションについて全体的に効率を向上させることができます。
注意
同時実行ランタイムによって作成されたスレッドからのみオーバーサブスクリプションを有効にします。ランタイムにより作成されたものではないスレッド (メイン スレッドを含みます) からオーバーサブスクリプションを呼び出しても効果はありません。
現在のコンテキストでオーバーサブスクリプションを有効にするには、trueに _BeginOversubscription パラメーターのセットを concurrency::Context::Oversubscribe のメソッドを呼び出します。 同時実行ランタイムにより作成されたスレッドに対しオーバーサブスクリプションを有効にすると、ランタイムにより追加スレッドが 1 つ作成されます。 オーバーサブスクリプションを必要とするすべてのタスクが終了した後、_BeginOversubscription パラメーターを false に設定して Context::Oversubscribe を呼び出します。
現在のコンテキストからオーバーサブスクリプションを複数回有効にできますが、有効にした回数と同じ回数無効にする必要があります。 オーバーサブスクリプションは入れ子にすることもできます。つまり、オーバーサブスクリプションを使用する別のタスクにより作成されるタスクもそのコンテキストをオーバーサブスクライブできます。 ただし、入れ子にされたタスクとその親の両方が同じコンテキストに属する場合、Context::Oversubscribe の最も外側の呼び出しによってのみ追加のスレッドが作成されます。
注意
ランタイムは有効になる前にオーバーサブスクリプションが無効になれば concurrency::invalid_oversubscribe_operation をスローします。
例
ネットワーク接続からのデータの読み込みが原因で発生する待機時間を、オーバーサブスクリプションを使用して短縮する例については、「方法: オーバーサブスクリプションを使用して待機時間を短縮する」を参照してください。
参照
処理手順
方法: スケジュール グループを使用して実行順序に影響を与える
方法: Context クラスを使用して協調セマフォを実装する
方法: オーバーサブスクリプションを使用して待機時間を短縮する