17
votes

I've implemented a WCF service as such:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single, UseSynchronizationContext=false)]
public sealed class SynchronizationService : ISynchronizationService, IDisposable
{
   private MemoryStream objectStream;

   ...
}

ISyncrhonizationService has [ServiceContract(SessionMode = SessionMode.Required)].

If a client communicates correctly and finally calls a method with [IsTerminating=true], then I can dispose of the objectStream variable nicely. If for some reason the communication between the service and the client gets disrupted, I'd like to clean up the objectStream variable from the service side myself, which is why I want to implement the IDisposable interface. But looking at the MSDN documentation (http://msdn.microsoft.com/en-us/library/system.idisposable.aspx) I'm a bit sceptical about this, because as per the documentation:

    // Dispose(bool disposing) executes in two distinct scenarios.
    // If disposing equals true, the method has been called directly
    // or indirectly by a user's code. Managed and unmanaged resources
    // can be disposed.
    // If disposing equals false, the method has been called by the
    // runtime from inside the finalizer and you should not reference
    // other objects. Only unmanaged resources can be disposed.

Because it's the runtime that will call the Dispose method then disposing = false. Thus I should not access objectStream, because it is a managed object. In this case the SyncrhonizationService finalizer provided by the runtime should clean up of objectStream itself and I don't need to implement IDisposable at all. Yet some forum posts suggest that the SyncrhonizationService instance will instead be reused and not disposed/finalized.

So my questions are:

1) What actually happens to the SyncrhonizationService instance during exceptions/faults/timeouts/etc? Will it be disposed or simply reused at a later time?

2) Do I need to implement IDisposable and do I dispose of managed objetcs inside the Dispose() method?

3) Is there perhaps a better alternative to IDisposable, for instance something like a channel_Faulted event? If I do dispose of my managed objects in such an event, how and where will I remove the event handler (I could do it in the event handler, but what if another type of exception/fault occurs)?

1
Note that IDisposable does not have a Dispose(bool) overload. The quoted comments from MSDN are documenting the code example given, not specifying IDisposable behaviour. The finalizer will not automatically call Dispose - you have to code it explicitly to do so as shown in the code example. Adding a Dispose(bool) override as shown in the code example is the standard pattern for doing this. In the case of your service, you can be confident that WCF will call your Dispose() method when the Session ends so you don't need (and shouldn't have) a finalizer.Chris Dickson
Thanks for clearing that up, now it all makes sense :)Marko

1 Answers

20
votes

If you implement IDisposable you can clean up managed objects inside your implementation of the Dispose() method.

With PerSession InstanceContextMode, the WCF runtime will call Dispose on your SynchronisationService object when the session ends, whether because the client closed his proxy; due to the session timing out through inactivity (on client or server); or through the channel faulting.

The service instance will not be reused: new sessions will get new instances of your SynchronisationService.