title: How to handle a delegate previously associated with a method of an object that now does no longer exist?
body: <p>I created a duplex service (<code>NetTcpBinding</code>) like <a href="http://msdn.microsoft.com/en-us/library/ms752254.aspx" rel="nofollow">this example</a>: 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.</p>
  
  <p>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...</p>
  
  <p>I wrote this example:</p>
  
  <ul>
  <li><code>MySingletonTable</code> is the data structure that stores the references to the methods of the callbacks;</li>
  <li><p><code>SampleService</code> is not a service, but simulates the instance of a service;</p>
  
  <pre><code>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&lt;string, ProcessingHandler&gt; pointersToHandlers;
  
      private MySingletonTable()
      {
          pointersToHandlers = new Dictionary&lt;string, ProcessingHandler&gt;();
      }
  
      // 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();
      }
  }
  </code></pre></li>
  </ul>
  
  <p>Obviously I can not explicitly destroy the two service instances simulated in this example. What would happen, however, if <code>s1</code> and <code>s2</code> were two instances of a service related to two different clients?</p>