Como: Selecione entre as tarefas concluídas

Este exemplo mostra como usar o Concurrency::choice e Concurrency::join classes 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 para concluir. Este exemplo define o employee o tipo, que contém um identificador numérico e um salário de um funcionário. O find_employee função localiza o primeiro funcionário que possui o identificador fornecido ou o salário fornecido. O find_employee função também manipula o caso em que nenhum funcionário tem o identificador fornecido ou salário. O wmain função cria uma matriz de employee objetos e procura por várias identificador e valores de salário.

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

  1. Um funcionário que tem o identificador fornecido existe.

  2. Um funcionário a quem foi o salário fornecido existe.

  3. Nenhum funcionário a quem foi o salário ou o identificador fornecido existe.

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

O exemplo usa um Concurrency::structured_task_group o objeto para executar os algoritmos de pesquisa em paralelo. Cada tarefa de pesquisa grava uma da single_assignment objetos para indicar se o funcionário específico existe. O exemplo usa o Concurrency::receive a função 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(employees.begin(), employees.end(), 
         [&](const employee& e) { return e.id == id; });
      if (result != employees.end())
      {
         // 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(employees.begin(), employees.end(), 
         [&](const employee& e) { return e.salary == salary; });
      if (result != employees.end())
      {
         // 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);
}

O exemplo produz a seguinte saída.

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 Concurrency::make_choice a função auxiliar para criar choice objetos e o Concurrency::make_join a função auxiliar para criar join objetos.

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

cl.exe /EHsc find-employee.cpp

Consulte também

Referência

Classe de opção

Classe de associação

Conceitos

Biblioteca de agentes assíncronos

Blocos de mensagens assíncronas

Funções de transmissão de mensagens