namespace WcfTicketingService {

 //...

}

public class SeatStatus {

 //---a string representing the seats booked by a client---

 public string Seats { get; set; }

}

The SeatStatus class contains Seats, a property for storing the seats booked by a client.

In the Service1.cs file, define the Ticketing class that implements the ITicketingService service contract:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.Text;

using System.Collections;

namespace WcfTicketingService {

 [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,

  ConcurrencyMode = ConcurrencyMode.Multiple)]

 public class Ticketing : ITicketService {

  //---used for locking---

  private object locker = new object();

  private SeatStatus _seatStatus = null;

  //---for storing all the clients connected to the service---

  private Dictionary<Client, ITicketCallBack> clients =

   new Dictionary<Client, ITicketCallBack>();

  public Ticketing() { }

  //---add a newly connected client to the dictionary---

  public void RegisterClient(Guid guid) {

   ITicketCallBack callback =

    OperationContext.Current.GetCallbackChannel<ITicketCallBack> ();

   //---prevent multiple clients adding at the same time---

   lock (locker) {

    clients.Add(new Client { id = guid }, callback);

   }

  }

  //---unregister a client by removing its GUID from

  // dictionary---

  public void UnRegisterClient(Guid guid) {

   var query = from c in clients.Keys

    where c.id == guid select c;

   clients.Remove(query.First());

  }

  //---called by clients when they want to book seats---

  public void SetSeatStatus(string strSeats) {

   _seatStatus = new SeatStatus {

    //---stores the seats to be booked by a client---

    Seats = strSeats

   };

   //---get all the clients in dictionary---

   var query = (from c in clients

    select c.Value).ToList();

   //---create the callback action delegate---

   Action<ITicketCallBack> action =

    delegate(ITicketCallBack callback) {

     //---callback to pass the seats booked

     // by a client to all other clients---

     callback.SeatStatus(_seatStatus.Seats);

    };

   //---for each connected client, invoke the callback---

   query.ForEach(action);

  }

 }

}

Within the Ticketing class are the implementations for the three operations defined in the ITicketService interface:

□ RegisterClient() — Called when clients are connected to the service for the first time. Clients are stored in a generic Dictionary<K,V> object. The key used for storing a client is its GUID, and its callback handler is stored as the value.

□ UnRegisterClient() — Called when a client is disconnected from the service; its entry in the Dictionary object is removed.

□ SetSeatStatus() — Called when clients want to book seats. The seats to be booked are stored in a SeatStatus object and then you create an Action delegate to invoke the callback of a client to pass the seats that have been booked by a client. Because all connected clients need to be notified, you invoke the callback for each client.

The [ServiceBehavior] attribute specifies the InstanceContextMode to be Single and the ConcurrencyMode property to be Multiple.

Service Behaviors — ConcurrencyMode

When messages are received by a WCF service, you can set how threads are used to manage all received messages:

□ One thread can be used to access the receiver object(s) at a time, or

□ Multiple threads can be used to access the receiver object(s) concurrently.

How you handle all incoming messages is specified using the ConcurrencyMode property of the [ServiceBehavior] attribute, which can assume one of the following values:

□ Single (default) — Only one thread can access the receiver object at a time.

□ Multiple — Multiple threads can access the receiver object(s) concurrently.

□ Reentrant — Only one thread can access the receiver object at a time, but callbacks can reenter that object on another thread.

When you use the Multiple mode on the service, take special care to make sure that threads are synchronized properly and that critical regions are locked when a threading is accessing it.

Вы читаете C# 2008 Programmer's Reference
Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату