Demonstra Passo a passo: Criando um aplicativo baseado em agente
Este tópico descreve como criar um aplicativo de baseado em agente básico. Esta explicação passo a passo, você pode criar um agente que lê dados de um arquivo de texto de forma assíncrona. O aplicativo usa o algoritmo de soma de verificação Adler-32 para calcular a soma de verificação do conteúdo do arquivo.
Pré-requisitos
Você deve compreender os tópicos a seguir para concluir este passo a passo:
Seções
Esta explicação passo a passo demonstra como realizar as seguintes tarefas:
Criando o aplicativo de Console
Criando a classe de file_reader
Usando a classe de file_reader no aplicativo
Criando o aplicativo de Console
Esta seção mostra como criar um aplicativo de console do Visual C++ que faz referência os arquivos de cabeçalho, o programa usará.
Para criar um aplicativo do Visual C++ usando o Assistente de aplicativo do Console Win32
No arquivo menu, clique em novae, em seguida, clique em projeto para exibir o Novo projeto caixa de diálogo.
No Novo projeto caixa de diálogo, selecione o Visual C++ nó na tipos de projeto painel e selecione Aplicativo de Console do Win32 na modelos painel. Digite um nome para o projeto, por exemplo, BasicAgente em seguida, clique em OK para exibir o Assistente de aplicativo de Console do Win32.
No Assistente de aplicativo de Console do Win32 caixa de diálogo, clique em Concluir.
Em stdafx. h, adicione o seguinte código.
#include <agents.h> #include <string> #include <iostream> #include <algorithm>
O agents.h do arquivo de cabeçalho contém a funcionalidade da Concurrency::agent classe.
Verifique se o aplicativo foi criado com êxito, criando e executando-o. Para criar o aplicativo, na Build menu, clique em Build Solution. Se o aplicativo foi criado com êxito, execute o aplicativo, clicando em Start Debugging sobre o Debug menu.
go to top
Criando a classe de file_reader
Esta seção mostra como criar o file_reader classe. O runtime agenda cada agente para realizar o trabalho em seu próprio contexto. Portanto, você pode criar um agente que realiza trabalho de forma síncrona, mas interage com outros componentes de forma assíncrona. O file_reader classe lê dados de um determinado arquivo de entrada e envia dados a partir desse arquivo para um componente de destino fornecido.
Para criar a classe file_reader
Adicione um novo arquivo de cabeçalho do C++ para seu projeto. Para fazer isso, clique com o botão direito do Arquivos de cabeçalho nó na Solution Explorer, clique em Adde, em seguida, clique em Novo Item. No modelos de painel, selecione O arquivo de cabeçalho (. h). No Add New Item caixa de diálogo, digite file_reader.h no nome caixa e, em seguida, clique em Add.
No file_reader.h, adicione o seguinte código.
#pragma once
No file_reader.h, criar uma classe chamada file_reader que deriva de agent.
class file_reader : public Concurrency::agent { public: protected: private: };
Adicione os seguintes membros de dados para o private seção da sua turma.
std::string _file_name; Concurrency::ITarget<std::string>& _target; Concurrency::overwrite_buffer<std::exception> _error;
O _file_name membro é o nome do arquivo que o agente lê. O _target membro é um Concurrency::ITarget que o agente grava o conteúdo do arquivo de objeto. O _error membro mantém qualquer erro que ocorre durante a vida útil do agente.
Adicione o seguinte código para o file_reader construtores para o public seção a file_reader classe.
explicit file_reader(const std::string& file_name, Concurrency::ITarget<std::string>& target) : _file_name(file_name) , _target(target) { } explicit file_reader(const std::string& file_name, Concurrency::ITarget<std::string>& target, Concurrency::Scheduler& scheduler) : agent(scheduler) , _file_name(file_name) , _target(target) { } explicit file_reader(const std::string& file_name, Concurrency::ITarget<std::string>& target, Concurrency::ScheduleGroup& group) : agent(group) , _file_name(file_name) , _target(target) { }
Cada sobrecarga de construtor define o file_reader membros de dados. A sobrecarga do construtor de segundo e terceiro permite que seu aplicativo para usar o Agendador de específico com seu agente. A primeira sobrecarga usa o agendador padrão com o seu agente.
Adicionar o get_error método para a seção pública da file_reader classe.
bool get_error(std::exception& e) { return try_receive(_error, e); }
O get_error método recupera qualquer erro que ocorre durante a vida útil do agente.
Implementar a Concurrency::agent::run método de protected seção da sua turma.
void run() { FILE* stream; try { // Open the file. if (fopen_s(&stream, _file_name.c_str(), "r") != 0) { // Throw an exception if an error occurs. throw std::exception("Failed to open input file."); } // Create a buffer to hold file data. char buf[1024]; // Set the buffer size. setvbuf(stream, buf, _IOFBF, sizeof buf); // Read the contents of the file and send the contents // to the target. while (fgets(buf, sizeof buf, stream)) { asend(_target, std::string(buf)); } // Send the empty string to the target to indicate the end of processing. asend(_target, std::string("")); // Close the file. fclose(stream); } catch (const std::exception& e) { // Send the empty string to the target to indicate the end of processing. asend(_target, std::string("")); // Write the exception to the error buffer. send(_error, e); } // Set the status of the agent to agent_done. done(); }
O run método abre o arquivo e lê os dados do proprietário. O run método usa o tratamento de exceção para capturar quaisquer erros que ocorrem durante o processamento do arquivo.
Cada vez que este método lê os dados do arquivo, ele chama o Concurrency::asend a função de enviar esses dados para o buffer de destino. Ele envia a seqüência de caracteres vazia para o buffer de destino para indicar o final do processamento.
O exemplo a seguir mostra todo o conteúdo da file_reader.h.
#pragma once
class file_reader : public Concurrency::agent
{
public:
explicit file_reader(const std::string& file_name,
Concurrency::ITarget<std::string>& target)
: _file_name(file_name)
, _target(target)
{
}
explicit file_reader(const std::string& file_name,
Concurrency::ITarget<std::string>& target,
Concurrency::Scheduler& scheduler)
: agent(scheduler)
, _file_name(file_name)
, _target(target)
{
}
explicit file_reader(const std::string& file_name,
Concurrency::ITarget<std::string>& target,
Concurrency::ScheduleGroup& group)
: agent(group)
, _file_name(file_name)
, _target(target)
{
}
// Retrieves any error that occurs during the life of the agent.
bool get_error(std::exception& e)
{
return try_receive(_error, e);
}
protected:
void run()
{
FILE* stream;
try
{
// Open the file.
if (fopen_s(&stream, _file_name.c_str(), "r") != 0)
{
// Throw an exception if an error occurs.
throw std::exception("Failed to open input file.");
}
// Create a buffer to hold file data.
char buf[1024];
// Set the buffer size.
setvbuf(stream, buf, _IOFBF, sizeof buf);
// Read the contents of the file and send the contents
// to the target.
while (fgets(buf, sizeof buf, stream))
{
asend(_target, std::string(buf));
}
// Send the empty string to the target to indicate the end of processing.
asend(_target, std::string(""));
// Close the file.
fclose(stream);
}
catch (const std::exception& e)
{
// Send the empty string to the target to indicate the end of processing.
asend(_target, std::string(""));
// Write the exception to the error buffer.
send(_error, e);
}
// Set the status of the agent to agent_done.
done();
}
private:
std::string _file_name;
Concurrency::ITarget<std::string>& _target;
Concurrency::overwrite_buffer<std::exception> _error;
};
go to top
Usando a classe de file_reader no aplicativo
Esta seção mostra como usar o file_reader classe para ler o conteúdo de um arquivo de texto. Ele também mostra como criar um Concurrency::call o objeto que recebe esse dados de arquivo e calcula a soma de verificação Adler-32.
Para usar a classe de file_reader em seu aplicativo.
Em BasicAgent.cpp, adicione o seguinte #include instrução.
#include "file_reader.h"
Em BasicAgent.cpp, adicione o seguinte using diretivas.
using namespace Concurrency; using namespace std;
No _tmain funcionar, crie um Concurrency::event o objeto que sinaliza o final do processamento.
event e;
Criar um call objeto que atualiza a soma de verificação quando ele recebe dados.
// The components of the Adler-32 sum. unsigned int a = 1; unsigned int b = 0; // A call object that updates the checksum when it receives data. call<string> calculate_checksum([&] (string s) { // If the input string is empty, set the event to signal // the end of processing. if (s.size() == 0) e.set(); // Perform the Adler-32 checksum algorithm. for_each(s.begin(), s.end(), [&] (char c) { a = (a + c) % 65521; b = (b + a) % 65521; }); });
Isso call objeto também define o event o objeto quando ele recebe a seqüência de caracteres vazia para sinalizar o final do processamento.
Criar um file_reader o objeto que lê a partir do txt de arquivo e grava o conteúdo desse arquivo para o call objeto.
file_reader reader("test.txt", calculate_checksum);
Inicie o agente e aguardar sua conclusão.
reader.start(); agent::wait(&reader);
Aguarde até que o call o objeto para receber todos os dados e concluir.
e.wait();
Verifique se o leitor de arquivo de erros. Se nenhum erro ocorreu, calcular a soma de Adler-32 final e imprimir a soma ao console.
std::exception error; if (reader.get_error(error)) { wcout << error.what() << endl; } else { unsigned int adler32_sum = (b << 16) | a; wcout << L"Adler-32 sum is " << hex << adler32_sum << endl; }
O exemplo a seguir mostra o arquivo completo do BasicAgent.cpp.
// BasicAgent.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "file_reader.h"
using namespace Concurrency;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
// An event object that signals the end of processing.
event e;
// The components of the Adler-32 sum.
unsigned int a = 1;
unsigned int b = 0;
// A call object that updates the checksum when it receives data.
call<string> calculate_checksum([&] (string s) {
// If the input string is empty, set the event to signal
// the end of processing.
if (s.size() == 0)
e.set();
// Perform the Adler-32 checksum algorithm.
for_each(s.begin(), s.end(), [&] (char c) {
a = (a + c) % 65521;
b = (b + a) % 65521;
});
});
// Create the agent.
file_reader reader("test.txt", calculate_checksum);
// Start the agent and wait for it to complete.
reader.start();
agent::wait(&reader);
// Wait for the call object to receive all data and complete.
e.wait();
// Check the file reader for errors.
// If no error occurred, calculate the final Adler-32 sum and print it
// to the console.
std::exception error;
if (reader.get_error(error))
{
wcout << error.what() << endl;
}
else
{
unsigned int adler32_sum = (b << 16) | a;
wcout << L"Adler-32 sum is " << hex << adler32_sum << endl;
}
}
go to top
Entrada de exemplo
Este é o conteúdo de amostra de text.txt o arquivo de entrada:
The quick brown fox
jumps
over the lazy dog
Saída de exemplo
Quando usado com a entrada de exemplo, este programa produz a seguinte saída:
Adler-32 sum is fefb0d75
Programação robusta
Para impedir o acesso simultâneo aos membros de dados, recomendamos que você adicione métodos que realizam um trabalho para o protected ou private seção da sua turma. Adicione apenas os métodos que enviar ou recebem mensagens de ou para o agente para o public seção da sua turma.
Sempre chamar o Concurrency::agent:: feito método para mover o seu agente para o estado concluído. Normalmente você chamar esse método antes de retornar a partir de run método.
Próximas etapas
Outro exemplo de um aplicativo baseado em agente, consulte Demonstra Passo a passo: Usando a associação para evitar o Deadlock.
Consulte também
Tarefas
Demonstra Passo a passo: Usando a associação para evitar o Deadlock
Conceitos
Biblioteca de agentes assíncronos
Blocos de mensagens assíncronas