I need my WAS hosted service (PerCall, Concurrency.Multiple) to shutdown/recycle gracefully but any inactive (but open) client proxies will block the service from shuttingdown gracefully.
I had expected the receiveTimout to kick in and toss out the inactive sessions but it looks like it doesn't work that way.
The IIS/WAS recycle will call ServiceHost.BeginClose with closing timeout set to TimeSpan.MaxValue.
I need to allow long lived client proxies (which I can not really control) with netTcpBinding, since throughput and low latency is a must.
I have reproduced the problem below and would be glad for any workarounds and help regarding the problem.
using System;
using System.ServiceModel;
namespace Test
{
[ServiceContract(Name = "MyService", SessionMode = SessionMode.Allowed)]
public interface IHelloWorldService
{
[OperationContract]
void PrintHelloWorld();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class HellowWorldService : IHelloWorldService
{
[OperationBehavior]
public void PrintHelloWorld()
{
Console.WriteLine("Hello world!");
}
}
public class ThaProgram
{
static void Main(string[] args)
{
const string ServiceAddress = "net.tcp://localhost:12345/HelloWorld";
var netTcpBinding = new NetTcpBinding(SecurityMode.None, false);
netTcpBinding.ReceiveTimeout = TimeSpan.FromSeconds(3);
var serviceHost = new ServiceHost(typeof(HellowWorldService), new Uri("net.tcp://localhost:12345"));
serviceHost.AddServiceEndpoint(typeof(IHelloWorldService), netTcpBinding, ServiceAddress);
serviceHost.Open();
Console.WriteLine("Service host state: {0}", serviceHost.State);
netTcpBinding.ReceiveTimeout = TimeSpan.FromSeconds(10);
var channel = new ChannelFactory<IHelloWorldService>(netTcpBinding, ServiceAddress).CreateChannel();
channel.PrintHelloWorld();
// Uncomment to make everything work (then the session will be closed before the service enters the closing state)
// Thread.Sleep(4000);
// Simulate application pool shutdown
var asyncResult = serviceHost.BeginClose(TimeSpan.MaxValue, null, null);
Console.WriteLine("Service host state: {0}", serviceHost.State);
serviceHost.EndClose(asyncResult);
Console.WriteLine("Service host state: {0}", serviceHost.State);
Console.WriteLine("Hit Enter to close the application");
Console.ReadLine();
}
}
}