Akka.NET is a toolkit and runtime for building highly concurrent, distributed, and fault tolerant event-driven applications on .NET and Mono. Instead of sharing state and managing concurrency ourselves Akka.NET handles this for us. We write the code in Actors, which has private state, runs in a single thread and interact with the outside via messages.
More information on Akka.NET can be found at http://akkadotnet.github.io/
Code for this post: https://github.com/HCanber/akka.net-blog-examples/tree/master/01-calculator
All posts in this series: Tutorials for Akka.NET
Note! This post explains how to create a simple calculator in Akka.NET. It was written when Akka.NET was in version 0.7.0 and might not work for later versions
Create the project
Start by creating a new Console App in Visual Studio.
Install the nuget package Akka
PM> Install-Package Akka
This is all that’s needed to start writing code for Akka.NET.
Create message classes
The only way to communicate with an actor is by messages (simple poco classes) .
In this example we’ll send an Add
message containing two integers to the calculator and we’ll get the answer as an Answer
message.
We define two classes to be our messages.
public class Add
{
private readonly double _term1;
private readonly double _term2;
public Add(double term1, double term2)
{
_term1 = term1;
_term2 = term2;
}
public double Term1 { get { return _term1; } }
public double Term2 { get { return _term2; } }
}
public class Answer
{
private readonly double _value;
public Answer(double value)
{
_value = value;
}
public double Value { get { return _value; } }
}
Why not Auto properties?
All messages must be immutable, otherwise we’ve open up for sharing state. Readonly fields ensures the messages are immutable.
The Calculator actor
Next is the CalculatorActor
. We’ll start off with an empty class, and inherit from ReceiveActor
:
using Akka.Actor;
public class CalculatorActor : ReceiveActor
{
public CalculatorActor()
{
}
}
That’s all we need for the CalculatorActor
for now. We’ll come back to it later.
Create the ActorSystem
Actors are run in an ActorSystem
and we need to create one.
using Akka.Actor;
namespace CalculatorApp
{
class Program
{
static void Main(string[] args)
{
var system = ActorSystem.Create("calculator-system");
}
}
}
Create a CalculatorActor instance
Now that we have a system, we can create a new instance of CalculatorActor
using system.ActorOf
.
var system = ActorSystem.Create("calculator-system");
ActorRef calculator = system.ActorOf<CalculatorActor>("calculator");
In this example we’ve also given it the name "calculator"
. This is optional, however since every actor must have a name, if you don’t give it a name it will be given a generated name. A good tip is to always name your actors . It will help when debugging, and when reading logs.
Send a message to the calculator
As you see above, ActorOf
returns an ActorRef
which acts as a proxy for the actual actor instance. This will allow us to communicate with the actor, without giving us access to any members exposed by the actor class.
The next step is to send it an Add
message.
ActorRef calculator = system.ActorOf<CalculatorActor>("calculator");
calculator.Tell(new Add(1, 2));
This will asynchronously send the Add
message to the calculator actor. But we haven’t defined how the actor should deal with messages so let’s do that.
Handling messages
The ReceiveActor
allows us to declare what will happen when different messages are received, and we do that in the constructor:
public class CalculatorActor : ReceiveActor
{
public CalculatorActor()
{
Receive<Add>(add => Sender.Tell(new Answer(add.Term1 + add.Term2)));
}
}
The Receive
statement says: When the actor receives a message of type Add
respond to the sender with an Answer
message.
Receiving responses
Next step is to receive the Answer
and print it to the console.
One way we to interact with actors from the outside and to receive responses is to use Ask
instead of Tell
. It will return a Task
on which we can await until a response is received.
So we switch to Ask
, await an Answer
(using the Result
property which will block the current thread) and then print the result.
static void Main(string[] args)
{
var system = ActorSystem.Create("calculator-system");
var calculator = system.ActorOf<CalculatorActor>("calculator");
var answer = calculator.Ask<Answer>(new Add(1, 2)).Result;
Console.WriteLine("Answer: "+answer.Value);
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
That’s it. Go ahead and run it. You should see:
Answer: 3
Press any key to exit
A note on Ask
While Ask
is very useful when interacting with actors from the outside be aware of that there are performance implications of using Ask
compared to using Tell
. So always prefer Tell
for performance, and only Ask
if you must.
Code
One file containing all code:
https://github.com/HCanber/akka.net-blog-examples/blob/master/01-calculator/CalculatorApp/Program.cs
Entire project: https://github.com/HCanber/akka.net-blog-examples/tree/master/01-calculator
Next
Next: Handling messages and state
All posts in this series: Tutorials for Akka.NET
No comments:
Post a Comment