Compartir a través de


Cómo: Seleccionar tareas completadas

En este ejemplo se muestra cómo utilizar el concurrency::choice y concurrency::join clases para seleccionar la primera tarea para completar un algoritmo de búsqueda.

Ejemplo

En el ejemplo siguiente se ejecutan dos algoritmos de búsqueda en paralelo y se selecciona el primer algoritmo para que se complete.En este ejemplo se define el tipo employee, que almacena un identificador numérico y un sueldo para un empleado.La función find_employee encuentra al primer empleado que tiene el identificador o el sueldo especificados.La función find_employee también controla el caso en el que ningún empleado tiene el identificador o el sueldo especificados.La función wmain crea una matriz de objetos employee y busca varios valores del identificador y del sueldo.

En el ejemplo se usa un objeto choice para realizar la selección entre los siguientes casos:

  1. Existe un empleado que tiene el identificador especificado.

  2. Existe un empleado que tiene el sueldo especificado.

  3. No existe ningún empleado con el identificador o el sueldo especificados.

Para los dos primeros casos, el ejemplo se utiliza un concurrency::single_assignment objeto para contener el identificador y otra single_assignment objeto para contener el salario.En el ejemplo se usa un objeto join para el tercer caso.El objeto join se compone de dos objetos single_assignment adicionales, uno para el caso en el que no existe ningún empleado con el identificador especificado y otro para el caso en el que no existe ningún empleado con el sueldo especificado.El objeto join envía un mensaje cuando cada uno de sus miembros recibe un mensaje.En este ejemplo, el objeto join envía un mensaje cuando no existe ningún empleado con el identificador o el sueldo especificados.

El ejemplo se utiliza un concurrency::structured_task_group objeto ejecutar ambos algoritmos de búsqueda en paralelo.Cada tarea de búsqueda escribe en uno de los objetos single_assignment para indicar si existe el empleado especificado.El ejemplo se utiliza la concurrency::receive función para obtener el índice del primer búfer que contiene un mensaje y un switch bloque para imprimir el resultado.

// find-employee.cpp
// compile with: /EHsc
#include <agents.h>
#include <ppl.h>
#include <array>
#include <iostream>
#include <random>

using namespace concurrency;
using namespace std;

// Contains information about an employee.
struct employee
{
   int id;
   float salary;
};

// Finds the first employee that has the provided id or salary.
template <typename T>
void find_employee(const T& employees, int id, float salary)
{
   // Holds the salary for the employee with the provided id.
   single_assignment<float> find_id_result;

   // Holds the id for the employee with the provided salary.
   single_assignment<int> find_salary_result;


   // Holds a message if no employee with the provided id exists.
   single_assignment<bool> id_not_found;

   // Holds a message if no employee with the provided salary exists.
   single_assignment<bool> salary_not_found;

   // Create a join object for the "not found" buffers.
   // This join object sends a message when both its members holds a message 
   // (in other words, no employee with the provided id or salary exists).
   auto not_found = make_join(&id_not_found, &salary_not_found);


   // Create a choice object to select among the following cases:
   // 1. An employee with the provided id exists.
   // 2. An employee with the provided salary exists.
   // 3. No employee with the provided id or salary exists.
   auto selector = make_choice(&find_id_result, &find_salary_result, &not_found);


   // Create a task that searches for the employee with the provided id.
   auto search_id_task = make_task([&]{
      auto result = find_if(begin(employees), end(employees), 
         [&](const employee& e) { return e.id == id; });
      if (result != end(employees))
      {
         // The id was found, send the salary to the result buffer.
         send(find_id_result, result->salary);
      }
      else
      {
         // The id was not found.
         send(id_not_found, true);
      }
   });

   // Create a task that searches for the employee with the provided salary.
   auto search_salary_task = make_task([&]{
      auto result = find_if(begin(employees), end(employees), 
         [&](const employee& e) { return e.salary == salary; });
      if (result != end(employees))
      {
         // The salary was found, send the id to the result buffer.
         send(find_salary_result, result->id);
      }
      else
      {
         // The salary was not found.
         send(salary_not_found, true);
      }
   });

   // Use a structured_task_group object to run both tasks.
   structured_task_group tasks;
   tasks.run(search_id_task);
   tasks.run(search_salary_task);

   wcout.setf(ios::fixed, ios::fixed);
   wcout.precision(2);

   // Receive the first object that holds a message and print a message.
   int index = receive(selector);
   switch (index)
   {
   case 0:
      wcout << L"Employee with id " << id << L" has salary " 
            << receive(find_id_result);
      break;
   case 1:
      wcout << L"Employee with salary " << salary << L" has id " 
            << receive(find_salary_result);
      break;
   case 2:
      wcout << L"No employee has id " << id << L" or salary " << salary;
      break;
   default:
      __assume(0);
   }
   wcout << L'.' << endl;

   // Cancel any active tasks and wait for the task group to finish.
   tasks.cancel();
   tasks.wait();
}

int wmain()
{
   // Create an array of employees and assign each one a 
   // random id and salary.

   array<employee, 10000> employees;

   mt19937 gen(15);
   const float base_salary = 25000.0f;
   for (int i = 0; i < employees.size(); ++i)
   {
      employees[i].id = gen()%100000;

      float bonus = static_cast<float>(gen()%5000);
      employees[i].salary = base_salary + bonus;
   }

   // Search for several id and salary values.

   find_employee(employees, 14758, 30210.00);
   find_employee(employees, 340, 29150.00);
   find_employee(employees, 61935, 29255.90);
   find_employee(employees, 899, 31223.00);
}

Este ejemplo produce el siguiente resultado.

Employee with id 14758 has salary 27780.00.
Employee with salary 29150.00 has id 84345.
Employee with id 61935 has salary 29905.00.
No employee has id 899 or salary 31223.00.

Este ejemplo se utiliza la concurrency::make_choice función auxiliar para crear choice los objetos y la concurrency::make_join función auxiliar para crear join objetos.

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 Buscar employee.cpp y, a continuación, ejecute el siguiente comando en una ventana de símbolo del sistema de Visual Studio.

cl.exe /EHsc find-employee.cpp

Vea también

Referencia

Clase choice

join (Clase)

Conceptos

Biblioteca de agentes asincrónicos

Bloques de mensajes asincrónicos

Funciones que pasan mensajes