Ho notato anche questo problema. mio codice è in origine si presentava così:
[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);
}
ho notato che il questo codice ha preso 20 run secondsto. Ho quindi deciso di chiudere le fabbriche di canale come questo:
[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();
}
Questo mi porta a credere che il lungo tempo necessario è lo smaltimento contesto istanza del cliente.
Sospetto che ci siano 3 modi per gestire meglio questa soluzione.
Il primo è creare una funzione sul client che gestisce la fine della sessione. In questo modo è possibile chiamare tale metodo prima che i piani di servizio si chiudano e accelererà il tempo di spegnimento.
il secondo è chiudere in modo asincrono ed eseguire altre elaborazioni mentre la connessione si sta chiudendo.
Il terzo è programmare nel client quando chiudere la connessione (soprattutto se si controllano sia il client che il servizio) in modo che il client possa terminare la sessione stessa e il servizio possa arrestarsi in modo semplice e rapido.
Sono sicuro che è possibile riorganizzare questo in modo che tutti i "s.Close()" vengano inviati per primi, quindi attendere il semaforo. –