I also noticed this problem. My code initially looked like this:
[TestMethod] [Timeout(2000)] public void ApiClientTest() { bool ApiSuccessSet, ClientSuccessSet = ApiSuccessSet = false; Api apiService = new ApiTestService(); var clientService = new ClientTestService(); ServiceHost clientHost = new ServiceHost(clientService, new Uri(PipeService)); ServiceHost apiHost = new ServiceHost(apiService, new Uri(PipeService)); //To let us know the services were successfully opened clientHost.Opened += (s, e) => ClientSuccessSet = true; apiHost.Opened += (s, e) => ApiSuccessSet = true; clientHost.AddServiceEndpoint(typeof(IClientService), new NetNamedPipeBinding(), ClientPipeServiceName); apiHost.AddServiceEndpoint(typeof(IApiService), new NetNamedPipeBinding(), ApiPipeServiceName); clientHost.BeginOpen(OnOpen, clientHost); apiHost.BeginOpen(OnOpen, apiHost); //This allows both services to be open for communication. while (!ApiSuccessSet || !ClientSuccessSet) Thread.Yield(); EndpointAddress ApiEndpoint = new EndpointAddress(PipeService + @"/" + ApiPipeServiceName); EndpointAddress clientEndpoint = new EndpointAddress(PipeService + @"/" + ClientPipeServiceName); InstanceContext context = new InstanceContext((IClientCallback)new TestClientCallback()); var ClientChannelFactory = new DuplexChannelFactory<IClientService>(context, new NetNamedPipeBinding(), clientEndpoint); var ApiChannelFactory = new ChannelFactory<IApiService>(new NetNamedPipeBinding(), ApiEndpoint); var ClientChannel = ClientChannelFactory.CreateChannel(); var ApiChannel = ApiChannelFactory.CreateChannel(); clientHost.Close(); apiHost.Close(); } void OnOpen(IAsyncResult ar) { ServiceHost service = (ServiceHost)ar.AsyncState; service.EndOpen(ar); }
I noticed that this code took 20 seconds. Then I decided to close the canal plants as follows:
[TestMethod] [Timeout(2000)] public void ApiClientTest() { bool ApiSuccessSet, ClientSuccessSet = ApiSuccessSet = false; Api apiService = new ApiTestService(); var clientService = new ClientTestService(); ServiceHost clientHost = new ServiceHost(clientService, new Uri(PipeService)); ServiceHost apiHost = new ServiceHost(apiService, new Uri(PipeService)); //To let us know the services were successfully opened clientHost.Opened += (s, e) => ClientSuccessSet = true; apiHost.Opened += (s, e) => ApiSuccessSet = true; clientHost.AddServiceEndpoint(typeof(IClientService), new NetNamedPipeBinding(), ClientPipeServiceName); apiHost.AddServiceEndpoint(typeof(IApiService), new NetNamedPipeBinding(), ApiPipeServiceName); clientHost.BeginOpen(OnOpen, clientHost); apiHost.BeginOpen(OnOpen, apiHost); //This allows both services to be open for communication. while (!ApiSuccessSet || !ClientSuccessSet) Thread.Yield(); EndpointAddress ApiEndpoint = new EndpointAddress(PipeService + @"/" + ApiPipeServiceName); EndpointAddress clientEndpoint = new EndpointAddress(PipeService + @"/" + ClientPipeServiceName); InstanceContext context = new InstanceContext((IClientCallback)new TestClientCallback()); var ClientChannelFactory = new DuplexChannelFactory<IClientService>(context, new NetNamedPipeBinding(), clientEndpoint); var ApiChannelFactory = new ChannelFactory<IApiService>(new NetNamedPipeBinding(), ApiEndpoint); var ClientChannel = ClientChannelFactory.CreateChannel(); var ApiChannel = ApiChannelFactory.CreateChannel(); ClientChannelFactory.Close(); ApiChannelFactory.Close(); clientHost.Close(); apiHost.Close(); }
This makes me think that it takes a long time to get rid of the context of the client instance.
I suspect there are 3 ways to better deal with this decision.
First, create a function on the client that controls session termination. Thus, you can call this method before the service plans are closed, and this will speed up the shutdown time.
the second is to close asynchronously and perform other processing until the connection closes.
The third is to program the client when you need to close the connection (especially if you manage both the client and the service) so that the client can end the session itself and the service can shut down gracefully and quickly.