Implementation Class
The implementation class, which should be named
MouseTracker.cs, is where you will place the majority of the service code. This includes message handlers, which contain the code that is executed when one of the DSS operations is called. The following important elements are contained in the implementation:
- ServiceState declaration
- ServicePort declaration
- Start method
- Message Handlers
As mentioned earlier, the service state contains useful information and represents the service at the time the state is requested. The
MousePos variable contains the actual mouse position, but the state itself is represented through a variable named
_state. This declaration is included at the top of the implementation class and is marked with the
ServiceState attribute, such as the following:
[ServiceState()]
private MouseTrackerState _state = new MouseTrackerState();
The
MouseTracker service utilizes a main port represented by the variable
_main. This is where the internal state is posted and the declaration should be preceded by the
ServicePort declaration, such as the following:
[ServicePort("/mousetracker", AllowMultipleInstances=false)]
private MouseTrackerOperations _mainPort = new MouseTrackerOperations();
In addition to the main port, the
MouseTracker service utilizes another port represented through the
_timerPort variable. The
TimerPort is used to post the date and time for the service timer. The timer is necessary because you'll need to constantly poll for the mouse position.
The Start method is the entry point for the service and it is called when service initialization is complete. It's primarily responsible for starting the service and this is where you'll add any code that needs to be executed at service startup. For the MouseTracker service, you'll include code to initialize the TimerPort and assign a handler for the Timer control. The code for the Start method is seen as follows:
protected override void Start()
{
base.Start();
// Activate the TimerHandler which will be used to
// get the mouse position
_timerPort.Post(DateTime.Now);
Activate(Arbiter.Receive(true, _timerPort,
TimerHandler));
}
The final things to add are the message handlers. For the
MouseTracker service, you'll need to associate a message handler with each of the message operations you've added to the
PortSet, as shown in
Listing 1.
You should notice that each handler is preceded by a ServiceHandler attribute. This attribute includes a property which indicates whether the code can execute concurrently with other code. For example, when the ServiceHanderBehavior is set to Exclusive, no other handlers can execute. When set to concurrent, other handlers are allowed to execute in parallel. This distinction should be made whenever the handler must update state. Just like when updating values in a database, you must ensure the integrity of the state data during updates.
In addition to the message operation handlers, you will need to add a handler for the timer control. This handler is activated in the Start method and should initiate a loop that executes every 1000 milliseconds. The TimerHandler uses the Arbiter class to set up a single item receiver that will handle notifications through the timer port. The code for this handler is seen in Listing 2.