RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Eliminate Server Polling with WCF Callbacks : Page 2

Client applications that share centralized information typically poll a central service to get updated information—a pull model. But by using WCF callbacks, the central service can push updated information to the clients in near-real time.

One-Way vs. Two-Way Operations
All the operations defined in the two interfaces are one-way operations (marked IsOneWay = true). To understand why, assume that all the operations use the default request/response model. When a client calls the SetSeatStatus() method to book seats, it will wait for a response from the service. However, the service will now invoke the SeatStatus callback on the client (the service informs all clients about the seats booked) and wait for a reply from the client. However, that would cause a deadlock, because the client would be waiting for a response from the service while the service would be waiting for a response from the client after invoking the callback. By defining the operations as one-way, the service can invoke the callback on the client without waiting for a reply from the client, thus eliminating the possibility of a deadlock.

Define the Classes
In the Service1.cs file, define the SeatStatus class:

   using System;
   using System.Text;
   using System.Timers;
   namespace WcfTicketingService
   public class SeatStatus
      //---a string representing the seats booked by a client---
      public string Seats { get; set; }
The SeatStatus class contains a property called Seats that stores the seats booked by a client.

Also in the Service1.cs file, define the Ticketing class, which implements the ITicketingService service contract (see Listing 1).

The Ticketing class contains the implementations for the three methods defined in the ITicketService interface:

  • RegisterClient(): Clients call this method when connecting to the service for the first time. The service stores the list of connected clients in a generic Dictionary object, using the GUID for the key, and it's the client's callback handler as the value.
  • UnRegisterClient(): Clients call this method when disconnecting from the service, which removes the calling client's entry from the Dictionary object.
  • SetSeatStatus(): Clients call this method to book seats. The seats to be booked are stored in a SeatStatus object. When seats are booked, the Ticketing class creates an Action delegate that invokes the callback of each client, passing the newly-booked seats.
Near the top of the code in Listing 1, the [ServiceBehavior] attribute specifies the InstanceContextMode property as Single and the ConcurrencyMode property as Multiple. When a WCF Service receives a message, the message gets dispatched to an object's instance methods. The options are:

  • A single instance of the receiver may be created for all clients
  • A single instance of the receiver may be created for each client
The InstanceContextMode property specifies the number of service instances available for handling calls contained in incoming messages. It can be one of the following:

  • Single: Every received message gets dispatched to the same object (a singleton).
  • Percall (default): Every received message is dispatched to a newly created object.
  • PerSession: Messages received within a session (usually a single sender) are dispatched to the same object.
  • Shareable: Messages received within a session (can be one or more senders) are dispatched to the same object.
You can also set how threads are used to manage all received messages, using either one thread at a time to access the receiver object(s), or using multiple threads to access the receiver object(s) concurrently.

The ConcurrencyMode property of the [ServiceBehavior] attribute controls how you handle all incoming messages. The property can assume of the following values:

  • Single (default): Only one thread may access the receiver object at a time
  • Multiple: Multiple threads may access the receiver object concurrently
  • Reentrant: Only one thread may access the receiver object at a time, but callbacks may re-enter that object on another thread
When you use the Multiple mode on the service, you need to take special care to make sure that threads are synchronized properly and that critical regions are locked during thread access.

To keep the demonstration simple, the sample project was developed using the following assumptions:

  • In real life, the application should save seats booked by a client in database or array; however for this example, they are simply broadcast to all connected clients.
  • When new clients connect to the server, the current seat allocation status (for instance, which seats are booked, which are not, etc.) should be sent to the client.
Now, double-click on the App.config file in Solution Explorer. Change the attribute values to match the following:

      <service name="WcfTicketingService.Ticketing" 
           <add baseAddress = 
              WcfTicketingService/Service1/" />
        <!-- Service Endpoints -->
        <!-- Unless fully qualified, address is 
             relative to base address supplied above -->
        <endpoint address ="" binding="wsHttpBinding" 
Right-click on the App.config file and select Edit WCF Configuration. Expand the EndPoints node (see Figure 3) and select the first [Empty Name] node.

Figure 3. Endpoint Properties: Visual Studio provides UI for setting the endpoint properties stored in App.config.

Figure 4. WCF Test Client: Although the WCF Test Client shows errors, that's normal for this application.
Set the endpoint properties as shown in Table 1.

Table 1. Endpoint Properties: Set the endpoint properties as shown in the table and illustrated in Figure 3.
Property Value
Address net.tcp://localhost:5000/TicketingService
Binding netTcpBinding

You will use TCP as the transport protocol.

Save the App.config file and close the configuration window. Press F5 to run and debug the service. In the WCF Test Client, you will see something like Figure 4. The error message is normal.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date