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