방법: 특정 Scheduler 정책 지정

스케줄러 정책을 사용하면 스케줄러가 작업을 관리할 때 사용하는 전략을 제어할 수 있습니다. 이 항목에서는 스케줄러 정책을 사용하여 진행률 표시기를 콘솔에 출력하는 작업의 스레드 우선 순위를 늘리는 방법을 보여 줍니다.

비동기 에이전트와 함께 사용자 지정 스케줄러 정책을 사용하는 예제는 방법: 특정 스케줄러 정책을 사용하는 에이전트 만들기를 참조하세요.

예시

다음 예제에서는 두 작업을 병렬로 수행합니다. 첫 번째 작업은 n번째 피보나치 번호를 계산합니다. 두 번째 작업은 진행률 표시기를 콘솔에 출력합니다.

첫 번째 작업은 재귀 분해를 사용하여 피보나치 번호를 계산합니다. 즉, 각 태스크는 전체 결과를 계산하기 위해 하위 작업을 재귀적으로 만듭니다. 재귀 분해를 사용하는 작업은 사용 가능한 모든 리소스를 사용할 수 있으므로 다른 작업이 굶어 죽을 수 있습니다. 이 예제에서는 진행률 표시기를 인쇄하는 작업이 컴퓨팅 리소스에 적시에 액세스하지 못할 수 있습니다.

컴퓨팅 리소스에 대한 진행률 메시지 공정한 액세스를 출력하는 작업을 제공하기 위해 이 예제에서는 방법: Scheduler 인스턴스 관리에서 사용자 지정 정책이 있는 스케줄러 인스턴스를 만드는 방법에 설명된 단계를 사용합니다. 사용자 지정 정책은 스레드 우선 순위를 가장 높은 우선 순위 클래스로 지정합니다.

이 예제에서는 동시성::callconcurrency::timer 클래스를 사용하여 진행률 표시기를 인쇄합니다. 이러한 클래스에는 동시성::Scheduler 개체를 예약하는 참조를 사용하는 생성자의 버전이 있습니다. 이 예제에서는 기본 스케줄러를 사용하여 Fibonacci 번호 및 스케줄러 인스턴스를 계산하는 작업을 예약하여 진행률 표시기를 출력하는 작업을 예약합니다.

사용자 지정 정책이 있는 스케줄러를 사용할 경우의 이점을 설명하기 위해 이 예제에서는 전체 작업을 두 번 수행합니다. 이 예제에서는 먼저 기본 스케줄러를 사용하여 두 작업을 모두 예약합니다. 그런 다음, 기본 스케줄러를 사용하여 첫 번째 작업을 예약하고 두 번째 작업을 예약하는 사용자 지정 정책이 있는 스케줄러를 사용합니다.

// 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 프로젝트에 붙여넣거나 이름이 지정된 scheduler-policy.cpp 파일에 붙여넣은 다음 Visual Studio 명령 프롬프트 창에서 다음 명령을 실행합니다.

cl.exe /EHsc scheduler-policy.cpp

참고 항목

스케줄러 정책
방법: 스케줄러 인스턴스 관리
방법: 특정 스케줄러 정책을 사용하는 에이전트 만들기