自学内容网 自学内容网

windows C++-创建基于代理的应用程序(上)

本文介绍了如何创建基本的基于代理的应用程序。 在这个案例中,你可以创建一个代理,从文本文件中异步读取数据。 应用程序使用 Adler-32 校验和算法来计算该文件内容的校验和。

创建控制台应用

本部分介绍了如何创建 C++ 控制台应用程序,用于引用程序将使用的头文件。 根据所使用的 Visual Studio 版本,初始步骤会有所不同。 若要查看 Visual Studio 首选项的文档,请使用“版本”选择器控件。 它位于此页面上目录表的顶部。

在 Visual Studio 中创建 C# 控制台应用程序
  1. 在主菜单中,选择“文件”>“新建”>“项目”,打开“创建新项目”对话框;
  2. 在对话框顶部,将“语言”设置为“C++”,将“平台”设置为“Windows”,并将“项目类型”设置为“控制台”;
  3. 从筛选的项目类型列表中,选择“控制台应用”,然后选择“下一步” 。 在下一页中,输入 BasicAgent 作为项目的名称,并根据需要指定项目位置;
  4. 选择“创建”按钮创建项目;
  5. 右键单击“解决方案资源管理器”中的项目节点,并选择“属性”。 在“配置属性”>“C/C++”>“预编译标头”>“预编译标头”下,选择“创建”;

注意: 这里演示了对默认情况下的项目改造,实际上,我们可以直接创建C++项目。

更新头文件

在 pch.h(Visual Studio 2017 及更早版本中为 stdafx.h)文件中,添加以下代码:

#include <agents.h>
#include <string>
#include <iostream>
#include <algorithm>

头文件 agents.h 包含 concurrency::agent 类的功能。

验证应用程序

最终,通过生成并运行应用程序来验证其是否已成功创建。 若要生成应用程序,请在“生成”菜单上单击“生成解决方案”。 如果应用程序已成功生成,请单击“调试”菜单上的“开始调试”来运行应用程序。

创建 file_reader 类

本部分介绍如何创建 file_reader 类。 运行时计划每个代理在其自己的上下文中执行工作。 因此,可以创建一个代理,该代理以同步方式执行工作,但与其他组件异步交互。 file_reader 类从给定输入文件读取数据,并将该文件中的数据发送到给定的目标组件。

创建 file_reader 类

1. 将新的 C++ 头文件添加到项目。 为此,请右键单击“解决方案资源管理器”中的“头文件”节点,单击“添加”,然后单击“新建项”。 在“模板”窗格中,选择“头文件(.h)”。 在“添加新项”对话框中,在“名称”框中键入 file_reader.h,然后单击“添加”。

2. 在 file_reader.h 中,添加以下代码:

#pragma once

3. 在 file_reader.h 中,创建一个派生自 agent 的名为 file_reader 的类。

class file_reader : public concurrency::agent
{
public:
protected:
private:
};

4. 将以下数据成员添加到类的 private 部分。

std::string _file_name;
concurrency::ITarget<std::string>& _target;
concurrency::overwrite_buffer<std::exception> _error;

_file_name 成员是代理从中读取的文件名。 _target 成员是代理向其写入文件内容的 concurrency::ITarget 对象。 _error 成员保留代理生命周期内发生的任何错误。

5. 将 file_reader 构造函数的以下代码添加到 file_reader 类的 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)
{
}

每个构造函数重载均设置 file_reader 数据成员。 第二和第三个构造函数重载使应用程序能够将特定的计划程序与代理一起使用。 第一个重载将默认的计划程序与代理一起使用。 

6. 将 get_error 方法添加到 file_reader 类的公共部分。

bool get_error(std::exception& e)
{
   return try_receive(_error, e);
}

get_error 方法检索代理生命周期内发生的任何错误。

7. 在类的 protected 部分实现 concurrency::agent::run 方法。

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

run 方法打开文件并从中读取数据。 run 方法使用异常处理来捕获文件处理期间发生的任何错误。

每次该方法从文件读取数据时,它都会调用 concurrency::asend 函数,将该数据发送到目标缓冲区。 它将空字符串发送到其目标缓冲区,以指示处理结束。


原文地址:https://blog.csdn.net/m0_72813396/article/details/142289999

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!