Compartilhar via


Como: Especificar políticas específicas do Agendador

As diretivas do Agendador lhe permitem controlar a estratégia que o Agendador usa quando ele gerencia as tarefas. Este tópico mostra como usar uma diretiva do Agendador para aumentar a prioridade do thread de uma tarefa que imprime um indicador de progresso para o console.

Para obter um exemplo que usa diretivas de Agendador personalizado juntamente com os agentes assíncronos, consulte Como: Criar agentes de políticas específicas do Agendador.

Exemplo

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

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

Para fornecer a tarefa que imprime um progresso mensagem fair acesso aos recursos de computação, este exemplo usa as etapas descritas na Como: Gerenciar uma instância do Agendador para criar uma instância de Agendador que tem uma diretiva personalizada. A diretiva personalizada Especifica a prioridade do thread como a classe de prioridade mais alta.

Este exemplo usa a Concurrency::call e Concurrency::timer classes para imprimir o indicador de progresso. Essas classes têm versões de seus construtores que levam a uma referência a um Concurrency::Scheduler objeto agenda-los. O exemplo usa o agendador padrão para agendar a 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 do uso de um Agendador de uma diretiva personalizada, este exemplo executa a tarefa geral duas vezes. Primeiro, o exemplo usa o agendador padrão para agendar a ambas as tarefas. O exemplo usa o agendador padrão para agendar a primeira tarefa e um Agendador de uma diretiva personalizada para agendar a tarefa de segunda.

// 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.

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

Embora ambos os conjuntos de tarefas de produzirem o mesmo resultado, a versão que usa uma diretiva personalizada permite que a tarefa que imprime o indicador de progresso para execução em uma prioridade elevada, para que ele se comporta mais responsively.

Compilando o código

Copie o código de exemplo e colá-lo em um Visual Studio do projeto, ou colá-lo em um arquivo que é chamado Agendador policy.cpp e, em seguida, execute o seguinte comando um Visual Studio 2010 janela do Prompt de comando.

cl.exe /EHsc scheduler-policy.cpp

Consulte também

Tarefas

Como: Criar agentes de políticas específicas do Agendador

Outros recursos

Diretivas do Agendador

Como: Gerenciar uma instância do Agendador