Search code examples
c#wcfservicehost

Where should I cleanup private resources for a ServiceHost?


I've set up a WCF NamedPipes Server/Client pair of applications but when the Host stops and calls ServiceHost.Close() it doesn't seem to appropriately cleanup the object from which the Host was created (using an object rather than a type to instantiate the host).

The server application code is as follows:

static void Main(string[] args) {
  // Specify the device type. Consider command line arguments here.
  DeviceTypes deviceType = DeviceTypes.myDeviceType;

  // Create the service object.
  ServiceHost selfHost = ServiceFactory.CreateService(deviceType);
  try {
    // Start the service.
    selfHost.Open();
    System.Console.WriteLine("The service is ready.");
    System.Console.WriteLine("Press <ENTER> to terminate service.");
    System.Console.WriteLine();
    System.Console.ReadLine();

    // Stop the service.
    System.Console.WriteLine("Closing the service.");
    selfHost.Close();
  } catch (CommunicationException e) {
    System.Console.WriteLine("An exception occurred: {0}", e.Message);
    selfHost.Abort();
  }
}

The ServiceFactory.CreateService method:

public static ServiceHost CreateService(DeviceTypes type) {
  // Create the client object.
  // Create_Server only creates an uninitialized child class based on the type.
  IMyServer client = MyServerFactory.Create_Server(type);

  // Initialize the client.
  client.Initialize();

  // Create the service object.
  MyService server = new MyService(client);

  // Create a service host.
  ServiceHost selfHost = new ServiceHost(server, new System.Uri(baseAddress));

  // Add a service endpoint.
  selfHost.AddServiceEndpoint(typeof(IMyActions), new NetNamedPipeBinding(), relAddress);
  return selfHost;
}

The MyService class (which contains the resource I want to clean up):

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = 
InstanceContextMode.Single)]
class MyService : IMyActions
{
    private IMyServer server;

    public MyService(IMyServer server) {
        this.server = server;
    }

    // Bunch of public operations to carry out the contract
    public bool Initialize() {
        return server.Initialize();
    }

    public void Dispose() {
        server.Dispose();
    }

    // No-op to check pipe connection.
    public void ConfirmConnection() { }
}

How and where should I call the server.Dispose() method in the MyService class? I thought that this would be handled by selfHost.Close() but it seems not...


Solution

  • Your output is a ServiceHost which is not a custom type you create. Therefore it will not automatically call IMyServer.Dispose().

    Instead of returning a ServiceHost, create some kind of adapter that will manage the ServiceHost and your IMyServer instance and return it to the void Main() method.

    Then, simply add a finally clause (or implement IDisposable and use using) and call your adapter's dispose, that will call serviceHost.Dispose() and myServer.Dispose().