Compartir a través de


Cómo: Especificar directivas de programador concretas

Las directivas de programador permiten controlar la estrategia que el programador utiliza cuando administra tareas.En este tema se muestra cómo utilizar una directiva de programador para aumentar la prioridad del subproceso de una tarea que imprime un indicador de progreso en la consola.

Para obtener un ejemplo que utiliza directivas de programador personalizadas junto con los agentes asincrónicos, vea Cómo: Crear agentes que usen directivas de programador específicas.

Ejemplo

En el siguiente ejemplo se llevan a cabo dos tareas en paralelo.La primera tarea calcula el número de Fibonacci cuyo orden es n.La segunda imprime un indicador de progreso en la consola.

La primera tarea utiliza la descomposición recursiva para calcular el número de Fibonacci.Es decir, cada tarea crea de forma recursiva subtareas para calcular el resultado total.Una tarea que utiliza la descomposición recursiva podría utilizar todos los recursos disponibles y dejar otras tareas sin alimentar.En este ejemplo, la tarea que imprime el indicador de progreso tal vez no reciba el acceso oportuno a los recursos de cálculo.

Para proporcionar a la tarea que imprime un mensaje de progreso un acceso adecuado a los recursos de cálculo, en este ejemplo se siguen los pasos que se describen en Cómo: Administrar una instancia del programador para crear una instancia del programador que tiene una directiva personalizada.La directiva personalizada especifica la prioridad del subproceso como la clase de prioridad máxima.

Este ejemplo se utiliza la concurrency::call y concurrency::timer clases para imprimir el indicador de progreso.Estas clases tienen las versiones de sus constructores que toman una referencia a un concurrency::Scheduler objeto horarios de ellos.En el ejemplo se utiliza el programador predeterminado para programar la tarea que calcula el número de Fibonacci y la instancia del programador para programar la tarea que imprime el indicador de progreso.

Para mostrar las ventajas de utilizar un programador que tiene una directiva personalizada, en el ejemplo se realiza la tarea dos veces.Primero se usa el programador predeterminado para programar ambas tareas.A continuación, se utiliza el programador predeterminado para programar la primera tarea y un programador que tiene una directiva personalizada para programar la segunda tarea.

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

Este ejemplo produce el siguiente resultado.

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

Aunque ambos conjuntos de tareas generan el mismo resultado, la versión que utiliza una directiva personalizada habilita la tarea que imprime el indicador de progreso para ejecutarse con una prioridad elevada de forma que responda con prontitud.

Compilar el código

Copie el código de ejemplo y péguelo en un proyecto de Visual Studio o lo pega en un archivo denominado policy.cpp-programador de y, a continuación, ejecute el siguiente comando en una ventana de símbolo del sistema de Visual Studio.

cl.exe /EHsc scheduler-policy.cpp

Vea también

Tareas

Cómo: Administrar una instancia del programador

Cómo: Crear agentes que usen directivas de programador específicas

Conceptos

Directivas del programador