I got a usual WCF service set up like this:
private ServiceHost serviceHost = null;
protected override void OnStart(string[] args)
{
if (serviceHost != null)
serviceHost.Close();
Uri[] baseAddress = new Uri[]{
new Uri("net.pipe://localhost")};
string PipeName = "DatabaseService";
serviceHost = new ServiceHost(typeof(Kernel), baseAddress); // Kernel implements IDatabase
serviceHost.AddServiceEndpoint(typeof(IDatabase), new NetNamedPipeBinding(), PipeName);
serviceHost.Open();
}
protected override void OnStop()
{
if (serviceHost != null && serviceHost.State != CommunicationState.Closed)
{
serviceHost.Close();
serviceHost = null;
}
}
From this code, i guess, one instance of “Kernel” is created, because I got this service running only once.
I create a proxy Object using the ChannelFactory like this:
pipeFactory = new ChannelFactory<IDatabase>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/DatabaseService"));
m_Database = pipeFactory.CreateChannel();
I have to say, that my Kernel instance access a local file, and therefore it’s very important I got only once physical instance of this class. I want my service to take care of that but here come’s my problem.
While the service is running and a single channel is created and active, a second client comes up and wants to create a channel too. That works properly but if I start using the proxy Object a FaultException is thrown because a second instance of my Kernel class is created.
Therefore I’m guessing that an instance of the Kernel class is created by every CreateChannel call.
Is it possible to avoid the creation of a new instance and return always a reference to a single Kernel class instance when CreateChannel is called?
Regards,
inva
Yes, by default, WCF uses the per-session or per-call calling convention, e.g. each incoming service request from a client gets a new, separate instance of your service (implementation) class.
You can control this, of course, using things like the
InstanceContextMode(PerSessionis the default – at least on bindings that support it -,PerCallthe recommended best practice, andSingleis the Singleton) and theConcurrencyModesettings on your service.You can define these either in config, or directly on your service class.
See the MSDN documentation on WCF Sessions, Instancing and Concurrency for a great and extensive explanation of all details. Also read the excellent MSDN Magazine article Discover Mighty Instance Management Techniques For Developing WCF Apps by Juval Lowy, a great resource always!
If you do switch your service class to be a singleton (
InstanceContextMode=InstanceContextMode.Single), you need to be aware of the two trade-offs:either you define the
ConcurrencyModeto also beSingle, which effectively means only one single request can ever be handled at once; requests will be serialized, that is, if handling the request takes a fairly long time, subsequent requests will have to start waiting and might end up timing outthe other option is to set the
ConcurrencyModetoMultiple, then your singleton service class can handle multiple requests at once; but this also means, you have to write your service class in a fully thread-safe manner and you need to synchronize and protect any concurrent access to shared data members – typically a very tricky and hard-to-do-right programming exercise