Using Call Context Initializers for Cleanup

I'm using framework features that have thread-local settings. These settings then get leaked to other client calls. How can I stop this from happening?

The problem here is that WCF doesn't know about these thread-local setting changes that you've made and so doesn't know that they need to be cleaned up. WCF by default is more frugal than other stacks, such as ASP.NET, when it comes to protecting state. Saving and restoring lots of thread-local settings takes time regardless of whether you actually did something with those settings or not. WCF tries not to do as much on your behalf so that you don't have to pay for cleanup unless you're using those features. It does however give you the hooks necessary to arrange for this cleanup to take place at the appropriate time.

The ICallContextInitializer interface lets you hook the beginning and end of operation calls. Hooking the end of the call allows you to cleanup these setting changes. It's easiest to insert an ICallContextInitializer by applying an endpoint behavior to your application endpoints.

 class MyInitializer : ICallContextInitializer
{
    public void AfterInvoke(object correlationState)
    {
       // Clean up thread-local settings here
    }

    public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
    {
       return null;
    }
}

class MyInitializerBehavior : IEndpointBehavior
{
    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
       // Add instances of your call context initializer to the CallContextInitializers collection
       // of the appropriate operations located at endpointDispatcher.DispatchRuntime.Operations.
    }

    public void Validate(ServiceEndpoint endpoint)
    {
    }
}

Next time we'll look at a more complete example of using ICallContextInitializer to solve a problem with setting up thread-local settings as well.

Next time: Using Call Context Initializers for Culture