I noticed this problem as well.
My code looks originally 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 the this code took 20 secondsto run. I then decided to close the channel factories 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();
ClientChannelFactory.Close();
ApiChannelFactory.Close();
clientHost.Close();
apiHost.Close();
}
This leads me to believe that the long time it takes is disposing the client's instance context.
I suspect that there are 3 ways to handle this solution better.
The first is to create a function on the client that manages ending the session. This way you can call that method before the service plans to shut down and it will speed up the shut down time.
the second is to close asynchronously and do other processing while the connection is closing.
The third is to program into the client when to close the connection (especially if you control both the client and the service) so that the client can terminate the session itself and the service can shut down gracefully and quickly.