The Proactor Pattern is an asynchronous event handling pattern. This pattern dispatches multiple events from multiple threads to the corresponding event handlers. This allows the application to have multiple operations running simultaneously without requiring the application to have a corresponding number of threads. Besides, it creates a "low coupling" and "high cohesion" between objects or a layered architecture.
Detailed information can be found in this book: Pattern-Oriented Software Architecture (Volume 2).
Some time ago, I implemented the Proactor pattern in C++ (STL), and wondered if I could make this pattern in C# and .NET. Since the .NET framework already provides a set of functionality, it became less time consuming than expected.
I'm sure (almost) every programmer could understand this pattern.
However, a set of programming and design skills are required which makes it easier to understand and to use this event handling pattern. Here is the set of skills which makes it easier to understand:
You should know a bit about:
- Singleton Pattern (see the GoF book)
- Locking shared data which can be accessed from multiple threads
- Bridge Pattern (GoF)
- How to realize a "low coupling" and "high cohesion" relationship between objects
Don't get daunted by me. It's reasonable, I think...
When to use this pattern?
Use this pattern if:
- you like to have an asynchronous event handling
- your objects should independently transport events
- your events should be delivered with different priority levels
- you like to realize "low coupling" and "high cohesion" between layers or objects
UML class diagram
This is the class diagram of the Proactor pattern.
The idea of this example is to let the
Bird fly (in software, of course). The
Bird will receive a
FlyEvent from another
Bird and will call its "fly away" method.
Dispatcher: the dispatcher dispatches the received events to the
Dispatchable object could receive events from the dispatcher.
PriorityQueue: this queue contains the enqueued events (ordered in separate priority queues).
Registry: contains the registered
IDipatchable: the interface to the
Dispatchable object which will receive asynchronous events from the dispatcher.
Here are the sequence diagrams:
Using the Proactor
Here is a set of instructions which must be done before using the Proactor Pattern.
- Every object which can receive an event must implement a
Dispatchable object and inherit from the
public class Bird : IDispatchable
private Dispatchable _dispatchable = new Dispatchable();
Why not inherit directly from the
You should now implement the methods provided in the
- Reason 1: this is high coupling and low cohesion, which we rather not want.
- Reason 2: data encapsulation.
public void HandleEvent(IEvent ievent)
Debug.Assert(ievent != null);
if (ievent is FlyEvent)
IDispatchable at the dispatcher (the
Bird does this in its constructor).
What does this Dispatcher do?
The heart of the Proactor Pattern is the
Dispatcher dispatches the enqueued events to the registered
Dispatchables in a (separate) thread.
private void Dispatch()
while (_dispachThread.ThreadState == System.Threading.ThreadState.Running)
if( _queue.Count >= 1 )
Dispatcher is a Singleton.
public static Dispatcher GetInstance
if (_instance == null)
_instance = new Dispatcher();
Keep in mind that events with a higher priority will be dispatched first. Be careful not to create starvation.
Time x: The
Dispatcher’s queue contains 210938 events with priority "Very High".
Time x + 1 millisecond: A "Very Low" priority event has been enqueued (and no further events will be enqueued).
Time x + 32365 milliseconds: the
Dispatcher's queue still contains 21 events with a priority "Very High".
The event enqueued at (Time + 1 ms) could be outdated. Don't get disappointed. There are mechanisms to prevent starvation, like a dynamic priority queue. The best part of having your own event handling mechanism is that such problems become suddenly...a challenge.
Create an event and enqueue it to the
Dispatcher. Decide the priority level of the event to enqueue.
FlyEvent fly = new FlyEvent();
fly, Dispatcher.Priority.Normal );
- Do not process too much in the
HandleEvent of the
- For the heroes, don’t be pessimistic prematurely.
To be continued
This Proactor Pattern could be extended with multiple patterns. I’ll wait on the responses first before I make a "Part 2" of this Pattern.