Practical ASP.NET

Distributed Concurrent Actor Models with Akka.NET

Ease the pain of concurrent programming with the Actor Model and Akka.NET.

Building concurrent systems that are capable of working on multiple pieces of work at the same time can be difficult, particularly when there's some shared mutable state being accessed by multiple threads.

The Actor Model gives you a way of representing systems using the higher-level abstractions of actors and messages. This can ease the burden of building concurrent systems.

Akka.NET is a port of the original Akka framework from Java/Scala to the Microsoft .NET Framework.

The Actor Model
The Actor Model describes a system whereby the fundamental unit of computation is the actor. A collection of actors performs the work of the system. Actors do not expose their internal state to the outside world (including other actors) but instead communicate via messages. The idea of this approach is to remove any shared mutable state; while actors do have mutable (internal) state, messages should be immutable.

An actor is able to do four essential things:

  • Respond to messages sent to it
  • Send messages to other actors
  • Create new actors
  • Change its behaviour in response to an incoming message

In Akka.NET, actors are classes that inherit from specific Akka.NET base classes, while messages can be simple .NET types such as a string, and they can also be custom types that are simple POCO classes.

Actors may exist in the same process on the same machine, different processes on the same machine, or even in different processes on different machines across the network. This ability to distribute actors out across multiple machines enables a system to scale out as required. One important feature in Akka.NET is that the code you write in your actors doesn't need to change depending on whether you're sending messages to a remote or local actor.

Defining an Akka.NET Actor
There is a choice of Akka.NET base classes to inherit from when defining an actor class, the basic being the untyped actor API. To get access to the core Akka.NET features the "Akka" NuGet package is installed.

In Listing 1 you can see an actor that's able to handle string or int messages that are sent to it.

Listing 1: Simple Actor Class Using the Untyped API
public class DemoActor : UntypedActor
{
  protected override void OnReceive(object message)
  {
    if (message is string)
    {
      // Do something with string message
      Console.WriteLine("Received string message {0}", message);
    }
    if (message is int)
    {
      // Do something with int message
      Console.WriteLine("Received int message {0}", message);
    }
    else
    {
      Unhandled(message);
    }
  }
}

An Actor System
In Akka.NET, actors live inside a managed actor system. This actor system manages the creation and lifetime of actors and the sending of messages around the system.

In Listing 2 you can see the Main method of a console application that creates an actor system, populates it with an actor instance and then sends a message to the actor using the Tell method.

Listing 2: Creating Actor Systems and Actor Instances
class Program
{
  static void Main(string[] args)
  {
    var actorSystem = ActorSystem.Create("DemoSystem");

    var actorReference = actorSystem.ActorOf<DemoActor>("DemoActor1");

    actorReference.Tell("hello");
    actorReference.Tell(123);

    // Wait for enter before closing console application
    Console.ReadLine();
  }
}

The output of running this code is shown in Figure 1.

[Click on image for larger view.] Figure 1. Console Application Showing Messages Being Received and Processed

Using Receive Actors
Receive actors offer a higher level API that does not require the kind of "if (message is string)" type statements. Instead the actor class inherits from the ReceiveActor base class and uses its Receive method to specify what types of messages it can handle. In Listing 3 we can see the same actor from Listing 1 refactored to a receive actor.

Listing 3: Inheriting from ReceiveActor
public class DemoActor : ReceiveActor
{
  public DemoActor()
  {
    Receive<string>(message =>
      {
        // do something with string message
        Console.WriteLine("Received string message {0}", message);
      });

    Receive<int>(message =>
      {
        // do something with int message
        Console.WriteLine("Received int message {0}", message);
      });
  }
}

This produces the same output when executed in the console application.

To find out more about Akka.NET, check out the project homepage at getakka.net.

About the Author

Jason Roberts is a Microsoft C# MVP with over 15 years experience. He writes a blog at http://dontcodetired.com, has produced numerous Pluralsight courses, and can be found on Twitter as @robertsjason.

comments powered by Disqus

Featured

  • VS Code Now Has Apple Silicon Builds for Native Mac Development

    Goodbye Rosetta, hello M1. Visual Studio Code has been updated with new builds that let it run natively on machines with Apple Silicon (M1), the company's own ARM64 chips.

  • Visual Studio 2019 for Mac v8.9 Ships with .NET 6 Preview 1 Support

    During its Ignite 2021 online event for IT pros and developers this week, Microsoft shipped Visual Studio 2019 for Mac v8.9, arriving with out-of-the-box support for .NET 6 Preview 1, which the company also released recently.

  • Analyst: TypeScript Now Firmly in Top 10 Echelon (Ruby, Not So Much)

    RedMonk analyst Stephen O'Grady believes TypeScript has achieved the rare feat of firmly ensconcing itself into the top 10 echelon of his ranking, now questioning how high it might go.

  • Black White Wave IMage

    Neural Regression Using PyTorch: Training

    The goal of a regression problem is to predict a single numeric value, for example, predicting the annual revenue of a new restaurant based on variables such as menu prices, number of tables, location and so on.

Upcoming Events