Compartilhar via


Como especificar políticas de agendador específicas

As políticas do agendador permitem controlar a estratégia que o agendador usa a gerenciar tarefas. Este tópico mostra como usar uma política do agendador para aumentar a prioridade de thread de uma tarefa que imprime um indicador de progresso no console.

Para obter um exemplo que usa políticas personalizadas do agendador junto com agentes assíncronas, consulte Como cria agentes que usam políticas de agendador específicas.

Exemplo

O exemplo a seguir executa duas tarefas em paralelo. A primeira tarefa computa o númeroº de Fibonacci em. A segunda tarefa imprime um indicador de progresso no console.

A primeira tarefa usa a decomposição recursiva para calcular o número de Fibonacci. Ou seja, cada tarefa cria subtarefas recursivamente para calcular o resultado total. Uma tarefa que usa a decomposição recursiva pode usar todos os recursos disponíveis, e morre de fome assim outras tarefas. Neste exemplo, a tarefa que imprime o indicador de progresso pode não receber acesso rápido possível para os recursos de computação.

Para fornecer a tarefa que imprime um acesso restrito da mensagem de progresso aos recursos de computação, etapas deste exemplo usa que são descritas em Como gerenciar uma instância de agendador para criar uma instância do agendador que tem uma política personalizado. A política personalizado especifica a prioridade de thread para ser a classe prioridade mais alta.

Este exemplo usa as classes de concurrency::call e de concurrency::timer para imprimir o indicador de progresso. Essas classes têm versões de seus construtores que usam uma referência a um objeto de concurrency::Scheduler que o agendamento. O exemplo usa o agendador padrão de agendamento da tarefa que calcula o número de Fibonacci e a instância do agendador para agendar a tarefa que imprime o indicador de progresso.

Para ilustrar os benefícios de usar um agendador que tem uma política personalizado, este exemplo executa a tarefa total duas vezes em. O primeiro exemplo usa o agendador padrão para agendar as duas tarefas. O exemplo usa o agendador padrão para agendar a primeira tarefa, e um agendador que tem uma política personalizado para agendar a segunda tarefa.

// 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);
}

O exemplo produz a seguinte saída.

  

Embora ambos os conjuntos de tarefas gerenciam o mesmo resultado, a versão que usa uma política personalizada permite que a tarefa que imprime o indicador de progresso para ser executado em uma prioridade alto de forma que se com comportamento mais respondendo.

Compilando o código

Copie o código de exemplo e cole-o em um projeto do Visual Studio, ou cole-o em um arquivo chamado scheduler-policy.cpp e execute o comando a seguir em uma janela de prompt de comando do Visual Studio.

cl.exe /EHsc scheduler-policy.cpp

Consulte também

Tarefas

Como gerenciar uma instância de agendador

Como cria agentes que usam políticas de agendador específicas

Conceitos

Políticas de agendador