I created a duplex service (NetTcpBinding
) like this example: I used the publish-subscribe pattern, and for each connection request from a new client, it creates a new instance of the service (containing a different callback). In this example, the callback is invoked through events and delegates.
Now I would like to change this example: suppose we do not want to respond immediately to client's request, that is, suppose we want to invoke the callback method after a certain time interval. In this case I need to maintain a reference to the method of the callback... But what happens if in the meantime some client disconnects? The service instance is destroyed and we lose even the callback...
I wrote this example:
MySingletonTable
is the data structure that stores the references to the methods of the callbacks;SampleService
is not a service, but simulates the instance of a service;public delegate void ProcessingHandler(string item, double price, double change); public class MySingletonTable { private static volatile MySingletonTable m_Instance; private static object syncRoot = new object(); private static Dictionary<string, ProcessingHandler> pointersToHandlers; private MySingletonTable() { pointersToHandlers = new Dictionary<string, ProcessingHandler>(); } // Return the singleton instance of this class. public static MySingletonTable Instance { get { if (m_Instance == null) { lock (syncRoot) { if (m_Instance == null) m_Instance = new MySingletonTable(); } } return m_Instance; } } /// The number of the entries in the table. public int Count { get { lock (syncRoot) { return pointersToHandlers.Count; } } } // Add an handler. public void Add(string id, ProcessingHandler handler) { lock (syncRoot) { if (!pointersToHandlers.ContainsKey(id)) pointersToHandlers.Add(id, handler); } } // Get an handler from the table. public ProcessingHandler GetHandler(string id) { ProcessingHandler handler = null; lock (syncRoot) { if (pointersToHandlers.ContainsKey(id)) handler = pointersToHandlers[id]; } return handler; } // Remove the specified handler. public bool Remove(string id) { lock (syncRoot) { return pointersToHandlers.Remove(id); } } } // This class simulates the service. public class SampleService { private static int counter = 0; private int service_i = ++counter; MySingletonTable reference = MySingletonTable.Instance; public SampleService(string id) { reference.Add(id, PriceChange); } private void PriceChange(string item, double price, double change) { // call the callback // ... Console.WriteLine("service_i {0}: {1} {2} {3}", service_i, item, price, change); } } class Program { static void Main(string[] args) { SampleService s1 = new SampleService("abc"); SampleService s2 = new SampleService("def"); MySingletonTable table = MySingletonTable.Instance; ProcessingHandler handler = null; handler = table.GetHandler("abc"); handler("item one", 10, 20); handler = table.GetHandler("def"); handler("item two", 30, 40); Console.ReadLine(); } }
Obviously I can not explicitly destroy the two service instances simulated in this example. What would happen, however, if s1
and s2
were two instances of a service related to two different clients?