locked
WCF Callback object destruction RRS feed

  • Question

  • I have a WCF Windows Service that hosts a WCF service that implements WCF callbacks.  When my client connects to the WCF service, the client calls a method to Subscribe to the WCF callback.  All of this works fine and the callback data is received by the callback whenever it is called.  I am using InstanceContextMode.PerSession for my WCF main class so that each new WCF client will have an instance of the service object until they close the connection (at least that is how I hope it works).

    My inquiry is regarding when and/or if the WCF object on the server side is finalized when the client disconnects.  The server side object registers itself as an event listener for a thread on its own process.  When the thread fires the event, the Callback is then called to pass the event onto the WCF client.  I have noticed that when the client disconnects, the server does not appear to finalize the WCF object that is associated with the client session.  I am thinking it is because the WCF server object is registerred as an event listener on another thread.  I thought that when an object goes out of context that it is automatically removed from any event handlers.  Maybe this is a wrong assumption.  Please correct me if it is.

    Anyhow, I want to know how I can be sure that I prevent memory leakage in my WCF Windows service when clients disconnect.  Any advice on how to do this properly would be appreciated.  Note, I do realize that the client can probably call an Unsubscribe() method, but I want to be able to be fault tolerant in case that method is not called since I cannot guarantee that the caller of the WCF server will call my Unsubscribe() method.

     

     

     

    Tuesday, July 13, 2010 7:40 PM

Answers

  • Hi

    You can implement IDisposable at the service level which will be called when the client closes the connection intentionally or not. In Dispose(), you can clean up all resources the service has used, including unregistering events.

    Hope this helps.

    Francois


    Please, mark the answer as helpful if it is. Thanks.
    • Marked as answer by Ken Varn Thursday, July 15, 2010 2:43 PM
    Tuesday, July 13, 2010 9:01 PM

All replies

  • Hi

    You can implement IDisposable at the service level which will be called when the client closes the connection intentionally or not. In Dispose(), you can clean up all resources the service has used, including unregistering events.

    Hope this helps.

    Francois


    Please, mark the answer as helpful if it is. Thanks.
    • Marked as answer by Ken Varn Thursday, July 15, 2010 2:43 PM
    Tuesday, July 13, 2010 9:01 PM
  • Hi

    You can implement IDisposable at the service level which will be called when the client closes the connection intentionally or not. In Dispose(), you can clean up all resources the service has used, including unregistering events.

    Hope this helps.

    Francois


    Please, mark the answer as helpful if it is. Thanks.


    That seems to work.  At least it does call the Dispose() method when the client disconnects.  However, I would hope that you would bear with me on one bit of confusion.  Do I actually have to explicitly remove the server WCF object from my event handler or will it be automatically removed by the garbage collector?

    Here is the class by the way.  Does this look like the correct way to do this?

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)]
      public class WCFSrv : IWCFSrv, IDisposable
      {
        private MASExecutive executive = MASExecutive.GetInstance();
        private IWCFSrvNotifier Callback;
        private MASExecutive.MASEventHandler myHandler;
    
        public bool Subscribe()
        {
          try
          {
            Callback = OperationContext.Current.GetCallbackChannel<IWCFSrvNotifier>();
            myHandler = new MASExecutive.MASEventHandler(mas_EventOccurred);
            executive.EventOccurred += myHandler;
    
            return true;
          }
          catch
          {
            return false;
          }
        }
    
        public bool UnSubscribe()
        {
          try
          {
            Callback = null;
            executive.EventOccurred -= myHandler;
    
            return true;
          }
          catch
          {
            return false;
          }
        }
    
        private void mas_EventOccurred(object sender, MASEventArgs e)
        {
          try
          {
            ICommunicationObject commObj = (ICommunicationObject) Callback;
    
            if (commObj.State == CommunicationState.Opened)
            {
              Callback.MASEvent(e);
            }
            else
            {
              UnSubscribe();
            }
          }
          catch { }
        }
    
        #region IDisposable Members
    
        public void Dispose()
        {
          UnSubscribe();
          GC.SuppressFinalize(this);
        }
    
        #endregion
      }
    

     

    Tuesday, July 13, 2010 9:27 PM
  • Hi Ken,

    I suggest you explicitly remove the eventhandler reference since the eventhandler does be a strong-reference if I remember correctly.

    Also, since you've used the following style code to cast the callback channel to ICommunicationObject, you can also try registring the Faulted event on it like:

     ICommunicationObject co = (ICommunicationObject)callbackChannel;
            co.Faulted +=new EventHandler(co_Faulted);
    
    so as to detect that when the client-side callback channel has encounter some error and stopped.

    BTW, for service instance, WCF provides the IInstanceProvider interface for developer to customize how the service instance is created and terminated (the lifecycle of the service instances):

    #IInstanceProvider Interface
    http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.iinstanceprovider.aspx


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Thursday, July 15, 2010 2:41 AM
  • Hi Ken,

    I suggest you explicitly remove the eventhandler reference since the eventhandler does be a strong-reference if I remember correctly.

    Also, since you've used the following style code to cast the callback channel to ICommunicationObject, you can also try registring the Faulted event on it like:

     ICommunicationObject co = (ICommunicationObject)callbackChannel;
    
        co.Faulted +=new EventHandler(co_Faulted);
    
    
    so as to detect that when the client-side callback channel has encounter some error and stopped.

    BTW, for service instance, WCF provides the IInstanceProvider interface for developer to customize how the service instance is created and terminated (the lifecycle of the service instances):

    #IInstanceProvider Interface
    http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.iinstanceprovider.aspx


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.


    Well, I hope that should pretty well cover it.  I added event handlers for Faulted and Closed just to make sure, but the Dispose() appears to be getting called on the disconnect as well (which is fine).  That allows me to remove the EventOccurred event handler and hopefully avoid a leak.  I have done the same for Faulted and Closed event on ICommunicationObject of Callback.

     

    Thursday, July 15, 2010 2:42 PM