Thoughts, Tips and Tricks on what I'm currently do for a living. Currently most of my spare time is spent on contributing to Akka.NET.

Sunday, October 26, 2014

Getting Started with Akka.NET

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.

Created with Raphaël 2.1.0ProgramProgramCalculatorCalculatorAdd(1, 2)Calculates 1+2Answer(3)

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