Introduction
In this article, I would like to give an example of a multi-agent solution on Windows platform using .NET Framework. I was working on a multi agent system where each agent was composed of C++ data processor application and a Java GUI application. This is a typical approach where some requirements have to be done very fast and there is a need for a GUI for human machine interface. This was a C2 (Command and Control System). Inter Agent and Intra Agent communication was through Corba. Now I am working on a new multi agent system where each agent is composed of a Windows service application (data processor application which has to be managed and fast) and a GUI Windows forms application. Now Inter Agent and Intra Agent communication is through .NET remoting. I would like to share my basic design behind the completely Windows based multi agent system.
Background
Taken from: Agent Technology Green Paper – Agent Working Group – OMG Document ec/99-12-02 Version 0.9
"A software agent is an autonomous software entity that can interact with its environment. Environment can be other agents, hardware, etc. Multiagents systems, then, are systems that are composed of coordinated agents together with the relationships that exist between them. For example in a kitchen, the toaster "knows" when the toast is done, and the coffeemaker "knows" when the coffee is ready. However, there is no cooperative environment here—only an environment with single agents. In a multiagent environment, the kitchen becomes more than just a collection of processors. Here, the appliances would be interconnected in such a way that the coffeemaker and the toaster would know that the coffee and toast be ready at the same time.
Some of the rationale for multiagent systems are as follows:
- One agent could be constructed that does everything, but fat agents represent a bottleneck for speed, reliability, maintainability, and so on (i.e., there are no omnipotent agents). Dividing functionality among many agents provides modularity, flexibility, modifiability, and extensibility.
- Specialized knowledge is not often available from a single agent (i.e., there are no omniscient agents). Knowledge that is spread over various sources (agents) can be integrated for a more complete view when needed.
- Applications requiring distributed computing are better supported by MAS. Here, agents can be designed as fine-grained autonomous components that act in parallel. Concurrent processing and problem solving can provide solutions to many problems that, up until now, we handled in a more linear manner. Agent technology, then, provides the ultimate in distributed component technology.
To support multiagent systems, an appropriate environment needs to be established. MAS environments:
- provide an infrastructure specifying communication and interaction protocols.
- are typically open and have no centralized designer or top-down control function.
- contain agents that are autonomous, adaptive, and coordinative.
Clearly, single-agent environments are much simpler because designers do not have to deal with issues such as cooperation, negotiation, and so on. However, the large-scale requirements of industry necessitates approaches requiring coordination and distribution."
Using the Code
My multi agent design is quite simple. There are multiple agents, they communicate with each other through .NET remoting and a global database. Each agent consists of a service application and a forms application. The Windows Form application part is optional. Sometimes there is no need for a human interface. I preferred service applications because services can be automatically started when the computer boots, can be paused and restarted, and do not show any user interface. These features make services ideal for use on a server or whenever you need long-running functionality that does not interfere with other users who are working on the same computer. And they are watched by the system, if they crash they can be restarted automatically.
Now let's talk about the example multi-agent system. System has 2 agents - temperature agent and time agent. ![Screenshot - GeneralDesignSmaller.gif](/KB/architecture/Multi-Agent_Software/GeneralDesignSmaller.gif)
Temperature agent gets the temperature from a virtual sensor (a random number generator) and gets the current time from the time agent and records it every 30 seconds. The user interface part of the temperature agent shows recorded temperatures in a table and shows the instant temperature.
Time management agent only publishes the current time. Nothing is recorded to the database. The user interface shows the current time.
Here is the design of the example multi-agent system.
Let's start with agent-agent communication. We only need a common DateTime
class. This class will be used between 2 agents and inside the time agent.
(Please refer to MSDN .NET Framework Remoting Overview, the examples are just great.)
Here we only create the datetime
class which is remotable:
public class ClassDateTime : MarshalByRefObject
{
private DateTime _dateTime;
public ClassDateTime()
{
_dateTime = DateTime.Now;
}
public void setDateTime(DateTime now)
{
_dateTime = now;
}
public DateTime getDateTime()
{
return _dateTime;
}
}
Let's continue with service application – Windows Forms application communication. We only need a common Temperature
class. This class will be used inside the temperature agent.
public class ClassTemperature : MarshalByRefObject
{
private int _temperature;
public void setTemperature(int temperature)
{
_temperature = temperature;
}
public int getTemperature()
{
return _temperature;
}
}
Now we can create the time agent service application. Please refer to the MSDN, Windows Service Applications section. We handle the remote object registration in the service constructor. When the time agent service application is started, it starts the timer which updates the remotable object every second.
public partial class ServiceTime : ServiceBase
{
private ClassDateTime _dateTime;
private System.Timers.Timer _timer;
public ServiceTime()
{
InitializeComponent();
TcpChannel serverChannel = new TcpChannel(9090);
ChannelServices.RegisterChannel(serverChannel);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(ClassDateTime), "RemoteObject.rem",
WellKnownObjectMode.Singleton);
_dateTime = (ClassDateTime)Activator.GetObject(
typeof(ClassDateTime),
"tcp://localhost:9090/RemoteObject.rem");
}
protected override void OnStart(string[] args)
{
_timer = new System.Timers.Timer();
_timer.Interval = 1000;
_timer.AutoReset = true;
_timer.Elapsed += new ElapsedEventHandler(PublishDateTime);
_timer.Start();
}
private void PublishDateTime(object sender, ElapsedEventArgs e)
{
_dateTime.setDateTime(DateTime.Now);
}
protected override void OnStop()
{
_timer.Stop();
}
Let's continue with the Temperature Agent service application. This agent is a client for the ClassDateTime
but server for the ClassTemperature
objects. We are initializing these objects in the constructor. This agent publishes the temperature every 2 seconds and records it in the database (XML file) every 10 seconds. These are done through 2 timer objects _timerPublishTemperature
and _timerWriteToXml
. Random temperature value is generated by a Random
object.
public partial class ServiceTemperature : ServiceBase
{
private ClassDateTime _dateTime;
private ClassTemperature _temperature;
private DataTable _globalDB;
private Random _autoRand;
private System.Timers.Timer _timerPublishTemperature;
private System.Timers.Timer _timerWriteToXml;
public ServiceTemperature()
{
InitializeComponent();
TcpChannel serverChannel = new TcpChannel(8080);
ChannelServices.RegisterChannel(serverChannel);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(ClassTemperature), "RemoteObject2.rem",
WellKnownObjectMode.Singleton);
_temperature = (ClassTemperature)Activator.GetObject(
typeof(ClassTemperature),
"tcp://localhost:8080/RemoteObject2.rem");
_dateTime = (ClassDateTime)Activator.GetObject(
typeof(ClassDateTime),
"tcp://localhost:9090/RemoteObject.rem");
_globalDB = new DataTable();
_globalDB.TableName = "RecordTable";
_globalDB.Columns.Add("Record DateTime", typeof(DateTime));
_globalDB.Columns.Add("Temperature", typeof(Double));
_autoRand = new Random();
}
protected override void OnStart(string[] args)
{
_timerPublishTemperature = new System.Timers.Timer();
_timerWriteToXml = new System.Timers.Timer();
_timerPublishTemperature.Interval = 2000;
_timerWriteToXml.Interval = 10000;
_timerPublishTemperature.AutoReset = true;
_timerWriteToXml.AutoReset = true;
_timerPublishTemperature.Elapsed += new ElapsedEventHandler(PublishTemperature);
_timerWriteToXml.Elapsed += new ElapsedEventHandler(WriteToXml);
_timerPublishTemperature.Start();
_timerWriteToXml.Start();
}
protected override void OnStop()
{
_timerWriteToXml.Stop();
_timerPublishTemperature.Stop();
}
private void PublishTemperature(object sender, ElapsedEventArgs e)
{
int tmp;
tmp = Convert.ToInt32(_autoRand.NextDouble() * 10);
_temperature.setTemperature(tmp);
}
private void WriteToXml(object sender, ElapsedEventArgs e)
{
int tmp;
tmp = Convert.ToInt32(_autoRand.NextDouble() * 10);
DataRow rowToAdd = _globalDB.NewRow();
rowToAdd[0] = _dateTime.getDateTime();
rowToAdd[1] = tmp;
_globalDB.Rows.Add(rowToAdd);
_globalDB.AcceptChanges();
_globalDB.WriteXml("C:\\globalDB.xml");
}
}
Now we can continue with the user interface part of the agents. The UI part of the Time Agent is quite simple. There is a button to start the timer which gets the current time from the service application part every 2 seconds.
public partial class FormMain : Form
{
private ClassDateTime _dateTime;
public FormMain()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
_dateTime = (ClassDateTime)Activator.GetObject(
typeof(ClassDateTime),
"tcp://localhost:9090/RemoteObject.rem");
timer1.Enabled = true;
}
private void timer1_Tick(object sender, EventArgs e)
{
labelCurDateTimeValue.Text =
Convert.ToString(_dateTime.getDateTime().ToString());
}
}
Temperature Agent user interface has a datagridview
to show the recorded data by the service application part. It also shows the instant temperature value gathered through .NET remoting. Start button starts the timer which gets the temperature value from the service application, and reads the recorded values from the database (XML file) and displays it in the datagridview
. In the solution, there is setup project which installs the service application parts of the agents.
public partial class FormMain : Form
{
ClassTemperature _temperature;
public FormMain()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
dataSet1.ReadXml("C:\\globalDB.xml");
dataGridView1.DataSource = dataSet1.Tables[0];
_temperature = (ClassTemperature)Activator.GetObject(
typeof(ClassTemperature),
"tcp://localhost:8080/RemoteObject2.rem");
timerMain.Enabled = true;
}
private void timerMain_Tick(object sender, EventArgs e)
{
labelTempValue.Text = _temperature.getTemperature().ToString();
}
}
After installing the service parts, you can start the services from Services control panel located in the Administrative Tools folder. Please start the WindowsServiceTimeAgent
first and then WindowsServiceTemperatureAgent
. Then you can run the user interface parts of the agents.
History
- 9th November, 2007: Initial post
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.