Share via


Comment : effectuer une sélection parmi les tâches terminées

Cet exemple montre comment utiliser la concurrency::choice et concurrency::join des classes pour sélectionner la première tâche à effectuer un algorithme de recherche.

Exemple

L'exemple suivant effectue deux algorithmes de recherche en parallèle et sélectionne le premier algorithme à terminer.Cet exemple définit le type employee, qui contient un identificateur numérique et un salaire pour un employé.La fonction find_employee recherche le premier employé qui a l'identificateur fourni ou le salaire fourni.La fonction find_employee gère également le cas où aucun employé n'a l'identificateur ou salaire fourni.La fonction wmain crée un tableau d'objets employee et recherche plusieurs valeurs de salaire et d'identificateur.

L'exemple utilise un objet choice pour effectuer une sélection parmi les cas suivants :

  1. Il existe un employé qui a l'identificateur fourni.

  2. Il existe un employé qui a le salaire fourni.

  3. Il n'existe aucun employé qui a l'identificateur ou le salaire fourni.

Pour les deux premiers cas, l'exemple utilise un concurrency::single_assignment objet pour contenir l'identificateur et l'autre single_assignment objet pour contenir le salaire.L'exemple utilise un objet join pour le troisième cas.L'objet join est composé de deux objets single_assignment supplémentaires, un pour le cas où il n'existe aucun employé avec l'identificateur fourni et un pour le cas où il n'existe aucun employé avec le salaire fourni.L'objet join envoie un message lorsque chacun de ses membres reçoit un message.Dans cet exemple, l'objet join envoie un message lorsqu'il n'existe aucun employé avec l'identificateur ou le salaire fourni.

L'exemple utilise un concurrency::structured_task_group objet pour exécuter les deux algorithmes de recherche en parallèle.Chaque tâche de recherche écrit dans l'un des objets single_assignment pour indiquer si l'employé donné existe.L'exemple utilise le concurrency::receive fonction pour obtenir l'index de la première mémoire tampon qui contient un message et un switch bloc pour imprimer le résultat.

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

Cet exemple génère la sortie suivante.

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.

Cet exemple utilise la concurrency::make_choice fonction d'assistance pour créer choice les objets et les concurrency::make_join fonction d'assistance pour créer join objets.

Compilation du code

Copiez l'exemple de code, collez-le dans un projet Visual Studio et collez-le dans un fichier nommé recherche employee.cpp , puis exécutez la commande suivante dans une fenêtre d'invite de commande Visual Studio.

cl.exe /EHsc find-employee.cpp

Voir aussi

Référence

Classe choice

join, classe

Concepts

Bibliothèque d'agents asynchrones

Blocs de messages asynchrones

Fonctions de passage de messages