For some design problems actors can make all the difference. An Actor in an independent entity that can respond to and send messages. In a way it is like its own little program running inside another process. But building actors in languages that don’t natively support them can be difficult.
The main problem that comes up is thread management. You usually don’t want to hijack the message sender’s thread as that would just give you method calling semantics. And allocating a separate thread to each actor doesn’t scale up past a dozen or so threads before context switching becomes a real problem.
Johan Olsson solved this dilemma for C# by building his actor library on top of TPL DataFlow. The purpose of TPL DataFlow is to chain together series of operations using asynchronous messages. As messages pass from one Block to the next they may be buffered, grouped, split, transformed, or otherwise manipulated according to the semantic and performance needs of the application.
At the core of his framework is an abstract class called Actor encapsulating an ActionBlock. The ActionBlock handles all of the threading issues internally so that the developer doesn’t need to deal with threads or tasks. Thread-safety comes from the fact that ActionBlocks are serialized by default. If you send two messages to it at one time it will buffer the second message until the first has been processed. This can be changed using the ExecutionDataflowBlockOptions class.
You can read more about Johan Olsson’s work and see example code in his post titled An actor model implementation in C# using TPL DataFlow.