Skip to content

Latest commit

 

History

History
208 lines (113 loc) · 11 KB

walkthrough-creating-an-agent-based-application.md

File metadata and controls

208 lines (113 loc) · 11 KB
description title ms.date helpviewer_keywords ms.assetid
Learn more about: Walkthrough: Creating an Agent-Based Application
Walkthrough: Creating an Agent-Based Application
10/27/2021
asynchronous agents, creating
agent class, example
730f42ce-6d58-4753-b948-fd9c9ef2ce6c

Walkthrough: Creating an Agent-Based Application

This topic describes how to create a basic agent-based application. In this walkthrough, you can create an agent that reads data from a text file asynchronously. The application uses the Adler-32 checksum algorithm to calculate the checksum of the contents of that file.

Prerequisites

You must understand the following topics to complete this walkthrough:

Sections

This walkthrough demonstrates how to perform the following tasks:

Creating the Console Application

This section shows how to create a C++ console application that references the header files that the program will use. The initial steps vary depending on which version of Visual Studio you are using. To see the documentation for your preferred version of Visual Studio, use the Version selector control. It's found at the top of the table of contents on this page.

::: moniker range=">=msvc-160"

To create a C++ console application in Visual Studio

  1. From the main menu, choose File > New > Project to open the Create a New Project dialog box.

  2. At the top of the dialog, set Language to C++, set Platform to Windows, and set Project type to Console.

  3. From the filtered list of project types, choose Console App then choose Next. In the next page, enter BasicAgent as the name for the project, and specify the project location if desired.

  4. Choose the Create button to create the project.

  5. Right-click the project node in Solution Explorer, and choose Properties. Under Configuration Properties > C/C++ > Precompiled Headers > Precompiled header choose Create.

::: moniker-end

::: moniker range="<=msvc-150"

To create a C++ console application in Visual Studio 2017 and earlier

  1. On the File menu, click New, and then click Project to display the New Project dialog box.

  2. In the New Project dialog box, select the Visual C++ node in the Project types pane and then select Win32 Console Application in the Templates pane. Type a name for the project, for example, BasicAgent, and then click OK to display the Win32 Console Application Wizard.

  3. In the Win32 Console Application Wizard dialog box, click Finish.

::: moniker-end

Update the header file

In the pch.h (stdafx.h in Visual Studio 2017 and earlier) file, add the following code:

[!code-cppconcrt-basic-agent#1]

The header file agents.h contains the functionality of the concurrency::agent class.

Verify the application

Finally, verify the application was created successfully by building and running it. To build the application, on the Build menu, click Build Solution. If the application builds successfully, run the application by clicking Start Debugging on the Debug menu.

[Top]

Creating the file_reader Class

This section shows how to create the file_reader class. The runtime schedules each agent to perform work in its own context. Therefore, you can create an agent that performs work synchronously, but interacts with other components asynchronously. The file_reader class reads data from a given input file and sends data from that file to a given target component.

To create the file_reader class

  1. Add a new C++ header file to your project. To do so, right-click the Header Files node in Solution Explorer, click Add, and then click New Item. In the Templates pane, select Header File (.h). In the Add New Item dialog box, type file_reader.h in the Name box and then click Add.

  2. In file_reader.h, add the following code.

    [!code-cppconcrt-basic-agent#17]

  3. In file_reader.h, create a class that is named file_reader that derives from agent.

    [!code-cppconcrt-basic-agent#2]

  4. Add the following data members to the private section of your class.

    [!code-cppconcrt-basic-agent#3]

    The _file_name member is the file name that the agent reads from. The _target member is a concurrency::ITarget object that the agent writes the contents of the file to. The _error member holds any error that occurs during the life of the agent.

  5. Add the following code for the file_reader constructors to the public section of the file_reader class.

    [!code-cppconcrt-basic-agent#4]

    Each constructor overload sets the file_reader data members. The second and third constructor overload enables your application to use a specific scheduler with your agent. The first overload uses the default scheduler with your agent.

  6. Add the get_error method to the public section of the file_reader class.

    [!code-cppconcrt-basic-agent#5]

    The get_error method retrieves any error that occurs during the life of the agent.

  7. Implement the concurrency::agent::run method in the protected section of your class.

    [!code-cppconcrt-basic-agent#6]

The run method opens the file and reads data from it. The run method uses exception handling to capture any errors that occur during file processing.

Each time this method reads data from the file, it calls the concurrency::asend function to send that data to the target buffer. It sends the empty string to its target buffer to indicate the end of processing.

The following example shows the complete contents of file_reader.h.

[!code-cppconcrt-basic-agent#7]

[Top]

Using the file_reader Class in the Application

This section shows how to use the file_reader class to read the contents of a text file. It also shows how to create a concurrency::call object that receives this file data and calculates its Adler-32 checksum.

To use the file_reader class in your application

  1. In BasicAgent.cpp, add the following #include statement.

    [!code-cppconcrt-basic-agent#8]

  2. In BasicAgent.cpp, add the following using directives.

    [!code-cppconcrt-basic-agent#9]

  3. In the _tmain function, create a concurrency::event object that signals the end of processing.

    [!code-cppconcrt-basic-agent#10]

  4. Create a call object that updates the checksum when it receives data.

    [!code-cppconcrt-basic-agent#11]

    This call object also sets the event object when it receives the empty string to signal the end of processing.

  5. Create a file_reader object that reads from the file test.txt and writes the contents of that file to the call object.

    [!code-cppconcrt-basic-agent#12]

  6. Start the agent and wait for it to finish.

    [!code-cppconcrt-basic-agent#13]

  7. Wait for the call object to receive all data and finish.

    [!code-cppconcrt-basic-agent#14]

  8. Check the file reader for errors. If no error occurred, calculate the final Adler-32 sum and print the sum to the console.

    [!code-cppconcrt-basic-agent#15]

The following example shows the complete BasicAgent.cpp file.

[!code-cppconcrt-basic-agent#16]

[Top]

Sample Input

This is the sample contents of the input file text.txt:

The quick brown fox
jumps
over the lazy dog

Sample Output

When used with the sample input, this program produces the following output:

Adler-32 sum is fefb0d75

Robust Programming

To prevent concurrent access to data members, we recommend that you add methods that perform work to the protected or private section of your class. Only add methods that send or receive messages to or from the agent to the public section of your class.

Always call the concurrency::agent::done method to move your agent to the completed state. You typically call this method before you return from the run method.

Next Steps

For another example of an agent-based application, see Walkthrough: Using join to Prevent Deadlock.

See also

Asynchronous Agents Library
Asynchronous Message Blocks
Message Passing Functions
Synchronization Data Structures
Walkthrough: Using join to Prevent Deadlock