次の方法で共有


方法: 特定のスケジューラ ポリシーを指定する

スケジューラでタスクを管理する場合、スケジューラ ポリシーを使用することで、スケジューラが使用する方法を制御できます。このトピックでは、スケジューラ ポリシーを使用して、プログレス インジケーターをコンソールに出力するタスクのスレッドの優先度を高くする方法について説明します。

カスタム スケジューラ ポリシーを非同期エージェントと共に使用する例については、「方法: 特定のスケジューラ ポリシーを使用するエージェントを作成する」を参照してください。

使用例

次の例では、2 つのタスクを並列で実行します。最初のタスクは、n 番目のフィボナッチ数を計算します。2 番目のタスクは、プログレス インジケーターをコンソールに出力します。

最初のタスクは、再帰的な分解を使用してフィナボッチ数を計算します。つまり、各タスクがサブタスクを再帰的に作成して全体的な結果を計算します。再帰的な分解を使用するタスクは、利用可能なすべてのリソースを使用するため、他のタスクが処理を続行できなくなる可能性があります。この例では、プログレス インジケーターを出力するタスクが、コンピューティング リソースに適切なタイミングでアクセスできない場合があります。

進行状況メッセージを出力するタスクがコンピューティング リソースに適切なタイミングでアクセスできるように、この例では、「方法: スケジューラ インスタンスを管理する」で説明されている手順に従って、カスタム ポリシーを持つスケジューラ インスタンスを作成しています。このカスタム ポリシーで、スレッドの優先順位が最も高い優先順位クラスとなるように指定します。

次の使用例を使用して、 concurrency::callconcurrency::timer クラスは、進行状況インジケーターを印刷します。これらのクラスへの参照を受け取るコンス トラクターのバージョンにある、 concurrency::Scheduler 、スケジュールを設定するオブジェクト。この例は、フィボナッチ数を計算するタスクをスケジュールする既定のスケジューラと、プログレス インジケーターを出力するタスクをスケジュールするスケジューラ インスタンスを使用します。

カスタム ポリシーを持つスケジューラを使用する利点を示すため、この例ではタスク全体を 2 度実行しています。まず、既定のスケジューラを使用して両方のタスクをスケジュールします。次に、既定のスケジューラを使用して最初のタスクをスケジュールし、カスタム ポリシーを持つスケジューラを使用して 2 番目のタスクをスケジュールします。

// scheduler-policy.cpp
// compile with: /EHsc
#include <windows.h>
#include <ppl.h>
#include <agents.h>
#include <iostream>

using namespace concurrency;
using namespace std;

// Computes the nth Fibonacci number.
// This function illustrates a lengthy operation and is therefore
// not optimized for performance.
int fibonacci(int n)
{
   if (n < 2)
      return n;

   // Compute the components in parallel.
   int n1, n2;
   parallel_invoke(
      [n,&n1] { n1 = fibonacci(n-1); },
      [n,&n2] { n2 = fibonacci(n-2); }
   );

   return n1 + n2;
}

// Prints a progress indicator while computing the nth Fibonacci number.
void fibonacci_with_progress(Scheduler& progress_scheduler, int n)
{
   // Use a task group to compute the Fibonacci number.
   // The tasks in this group are scheduled by the current scheduler.
   structured_task_group tasks;

   auto task = make_task([n] {
      fibonacci(n);
   });
   tasks.run(task);

   // Create a call object that prints its input to the console.
   // This example uses the provided scheduler to schedule the 
   // task that the call object performs.
   call<wchar_t> c(progress_scheduler, [](wchar_t c) { 
      wcout << c; 
   });

   // Connect the call object to a timer object. The timer object
   // sends a progress message to the call object every 100 ms.
   // This example also uses the provided scheduler to schedule the 
   // task that the timer object performs.
   timer<wchar_t> t(progress_scheduler, 100, L'.', &c, true);
   t.start();

   // Wait for the task that computes the Fibonacci number to finish.
   tasks.wait();

   // Stop the timer.
   t.stop();

   wcout << L"done" << endl;
}

int wmain()
{  
   // Calculate the 38th Fibonacci number.
   const int n = 38;

   // Use the default scheduler to schedule the progress indicator while 
   // the Fibonacci number is calculated in the background.

   wcout << L"Default scheduler:" << endl;
   fibonacci_with_progress(*CurrentScheduler::Get(), n);

   // Now use a scheduler that has a custom policy for the progress indicator.
   // The custom policy specifies the thread priority to the highest 
   // priority class.

   SchedulerPolicy policy(1, ContextPriority, THREAD_PRIORITY_HIGHEST);
   Scheduler* scheduler = Scheduler::Create(policy);

   // Register to be notified when the scheduler shuts down.
   HANDLE hShutdownEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
   scheduler->RegisterShutdownEvent(hShutdownEvent);

   wcout << L"Scheduler that has a custom policy:" << endl;
   fibonacci_with_progress(*scheduler, n);

   // Release the final reference to the scheduler. This causes the scheduler
   // to shut down.
    scheduler->Release();

   // Wait for the scheduler to shut down and destroy itself.
   WaitForSingleObject(hShutdownEvent, INFINITE);

   // Close the event handle.
   CloseHandle(hShutdownEvent);
}

この例を実行すると、次の出力が生成されます。

Default scheduler:
...........................................................................done
Scheduler that has a custom policy:
...........................................................................done

どちらのタスク セットでも結果は同じですが、カスタム ポリシーを使用するバージョンではプログレス インジケーターを出力するタスクを高い優先順位で実行できるため、応答性が向上します。

コードのコンパイル

コード例をコピーして、Visual Studio プロジェクトでは、貼り付けるまたはという名前のファイルに貼り付けてスケジューラ policy.cpp と、Visual Studio のコマンド プロンプト ウィンドウで次のコマンドを実行します。

cl.exe /EHsc scheduler-policy.cpp

参照

処理手順

方法: スケジューラ インスタンスを管理する

方法: 特定のスケジューラ ポリシーを使用するエージェントを作成する

概念

スケジューラ ポリシー