Partilhar via


Como: Selecionar entre tarefas concluídas

Este exemplo mostra como usar as classes concurrency::choice e concurrency::join para selecionar a primeira tarefa para concluir um algoritmo de pesquisa.

Exemplo

O exemplo a seguir executa dois algoritmos de pesquisa em paralelo e seleciona o primeiro algoritmo a ser concluído. Este exemplo define o employee tipo, que contém um identificador numérico e um salário para um funcionário. A find_employee função encontra o primeiro funcionário que tem o identificador fornecido ou o salário fornecido. A find_employee função também lida com o caso em que nenhum funcionário tem o identificador fornecido ou salário. A wmain função cria uma matriz de employee objetos e procura vários identificadores e valores salariais.

O exemplo usa um choice objeto para selecionar entre os seguintes casos:

  1. Existe um funcionário que tenha o identificador fornecido.

  2. Existe um funcionário que tem o salário fornecido.

  3. Não existe nenhum funcionário que tenha o identificador ou salário fornecido.

Para os dois primeiros casos, o exemplo usa um objeto concurrency::single_assignment para manter o identificador e outro single_assignment objeto para manter o salário. O exemplo usa um join objeto para o terceiro caso. O join objeto é composto por dois objetos adicionais single_assignment , um para o caso em que não existe nenhum funcionário que tenha o identificador fornecido e outro para o caso em que não existe nenhum funcionário que tenha o salário fornecido. O join objeto envia uma mensagem quando cada um de seus membros recebe uma mensagem. Neste exemplo, o join objeto envia uma mensagem quando não existe nenhum funcionário que tenha o identificador ou salário fornecido.

O exemplo usa um objeto concurrency::structured_task_group para executar ambos os algoritmos de pesquisa em paralelo. Cada tarefa de pesquisa grava em um dos objetos single_assignment para indicar se o funcionário dado existe. O exemplo usa a função concurrency::receive para obter o índice do primeiro buffer que contém uma mensagem e um switch bloco para imprimir o 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 exemplo produz o seguinte 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 exemplo usa a função auxiliar concurrency::make_choice para criar choice objetos e a função auxiliar concurrency::make_join para criar join objetos.

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 find-employee.cpp e, em seguida, execute o seguinte comando em uma janela do prompt de comando do Visual Studio.

cl.exe /EHsc find-employee.cpp

Ver também

Biblioteca de agentes assíncronos
Blocos de mensagens assíncronas
Funções de passagem de mensagens
escolha Classe
Entrar na turma