Browse DevX
Sign up for e-mail newsletters from DevX


Eliminate Server Polling with WCF Callbacks : Page 3

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.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Building the Client
With the WCF service completed, you can now build the client that consumes the service. Using the same solution, add a new Windows Forms Application project, named Client.

Add a service reference to the WCF ticketing service (in the Add Service Reference dialog, click the Discover button and you should be able to discover the Ticketing WCF service (see Figure 5). Select it, and then click OK.

Figure 5. Add Service Reference: Using the Add Service Reference dialog, add a reference to the WCF ticketing service.
Figure 6. Sample Controls: Populate Form1 with the controls shown in this figure.

Next, populate Form1 with the controls shown in Figure 6. Set the form's Size property to 477, 387.

In the code-behind for Form1, import the namespace shown below, and then declare the following constants and objects:

using System.ServiceModel; namespace Client { public partial class Form1 : Form { int ROWS = 10; int COLUMNS = 10; const int SEAT_WIDTH = 45; const int SEAT_HEIGHT = 25; const int START_X = 10; const int START_Y = 40; static Button[,] seatsArray; private ServiceReference1.TicketingServiceClient _client; private Guid _guid = Guid.NewGuid();

Define the SeatsOccupied() static function within the Form1 class as follows:

public partial class Form1 : Form { ... ... ... //---set all occupied seats in red--- public static void SeatsOccupied(string strSeatsOccupied) { string[] seats = strSeatsOccupied.Split(','); for (int i = 0; i < seats.Length - 1; i++) { string[] xy = seats[i].Split('-'); Button btn = seatsArray[int.Parse(xy[0]) - 1, int.Parse(xy[1]) - 1]; btn.BackColor = Color.Red; } } }

The SeatsOccupied function in the preceding code accepts a string containing the seats that are occupied. You'll see more about that in a minute. The seats themselves will be represented by button controls. Whenever a user books a seat (using the Button control), the application changes that seat's background color to red (meaning it's reserved).

Define the SeatStatusCallback class and implement the SeatStatus() method as defined in the TicketingServiceCallback interface (defined in the service):

namespace Client { public partial class Form1 : Form { //... } public class SeatStatusCallback : ServiceReference1.TicketingServiceCallback { public void SeatStatus(string message) { Form1.SeatsOccupied(message); } } }

The client invokes the SeatStatus() method when the web service calls the client's callback. In this case, you call the static SeatsOccupied() function to update the seats status.

Code the Form1_Load event handler as follows:

private void Form1_Load(object sender, EventArgs e) { InstanceContext context = new InstanceContext(new SeatStatusCallback()); _client = new ServiceReference1.TicketingServiceClient(context); _client.RegisterClient(_guid); //---display the seats--- seatsArray = new Button[COLUMNS, ROWS]; for (int r = 0; r < ROWS; r++) { for (int c = 0; c < ROWS; c++) { Button btn = new Button(); btn.Location = new Point( START_X + (SEAT_WIDTH * c), START_Y + (SEAT_HEIGHT * r)); btn.Size = new Size(SEAT_WIDTH, SEAT_HEIGHT); btn.Text = (c + 1).ToString() + "-" + (r + 1).ToString(); btn.BackColor = Color.White; seatsArray[c, r] = btn; btn.Click += new EventHandler(btn_Click); this.Controls.Add(btn); } } }

The preceding code basically creates an instance of the InstanceContext class by passing it an instance of the SeatStatusCallback class. It then creates an instance of the WCF client using the constructor (which requires an InstanceContext object). In addition, it dynamically populates the form with a 10x10 array of Button controls that represent the seats, and wires each Button control's Click event to the btn_Click event handler, shown below:

void btn_Click(object sender, EventArgs e) { if (((Button)sender).BackColor == Color.White) { ((Button)sender).BackColor = Color.Yellow; } else if (((Button)sender).BackColor == Color.Yellow) { ((Button)sender).BackColor = Color.White; } }

This event handler toggles the color of the seats as users click on the Button controls. White indicates that the seat is available; yellow indicates that the seat has been selected for booking.

Code the Book Seats button as follows:

private void btnBookSeats_Click(object sender, EventArgs e) { string seatsToBook = string.Empty; for (int r = 0; r < ROWS; r++) { for (int c = 0; c < ROWS; c++) { if (seatsArray[c, r].BackColor == Color.Yellow) { seatsToBook += seatsArray[c, r].Text + ,""; } } } //---send to WCF service--- _client.SetSeatStatus(seatsToBook); }

To specify the seats that are selected for booking, create the string containing the seats to be booked in the following format:


Finally, code the Form1_FormClosing event so it calls the web service to unregister the client, as follows:

private void Form1_FormClosing(object sender, FormClosingEventArgs e) { _client.UnRegisterClient(_guid); }

Testing the Application
To test the application, press F5 to debug and launch the service. When it's running, you can debug the client. Right-click on the Client project in Solution Explorer, and select Debug → Start new instance. (See Figure 7).

Figure 7. Launching the Client: To debug an instance of the client, right-click on the client project in Solution Explorer, and select Debug ( Start new instance.
Figure 8. Real-Time Updates: When one client books seats, all the clients get updated in near real-time.

Run a few instances of the client and you can then start to book cinema tickets. Notice that as one client books the seats, the service updates the other clients automatically (see Figure 8).

That completes the example. You've seen how you to use WCF callbacks to implement a cinema ticketing system, and you have an example you can extend to meet your own needs. Callbacks are advantageous because they allow asynchronous communications between a client and a service, and eliminate the need to constantly poll the service.

Wei-Meng Lee is a Microsoft MVP and founder of Developer Learning Solutions, a technology company specializing in hands-on training on the latest Microsoft technologies. He is an established developer and trainer specializing in .NET and wireless technologies. Wei-Meng speaks regularly at international conferences and has authored and coauthored numerous books on .NET, XML, and wireless technologies. He writes extensively on topics ranging from .NET to Mac OS X. He is also the author of the .NET Compact Framework Pocket Guide, ASP.NET 2.0: A Developer's Notebook (both from O'Reilly Media, Inc.), and Programming Sudoku (Apress). Here is Wei-Meng's blog.
Thanks for your registration, follow us on our social networks to keep up-to-date