in the process of creating a WCF service I ran into a term that's new to me. Basically when specifying the InstanceContextMode
I have a few options, including; PerSession
, PerCall
and Single
. Here's the code from the sample I'm learning from:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class EvalService : IEvalService { ...
Now, he stated by doing this that only one instance of my service would be created at runtime. What does this mean? I thought that everytime a connection was made to the web service that it was treated as a seperate instance.
Does it persist, this instance of my service, for every request made? Judging by the other members mentioned in the docs, is it safe to assume this is the way it works?
Per-call service is the default instance activation mode of WCF. When a WCF service is configured for a per-call service, a CLR object is created for the timespan a client call or request is in progress.
Windows Communication Foundation (WCF) is a framework for building service-oriented applications. Using WCF, you can send data as asynchronous messages from one service endpoint to another. A service endpoint can be part of a continuously available service hosted by IIS, or it can be a service hosted in an application.
Visual Studio provides tools for working with Windows Communication Foundation (WCF) and WCF Data Services, Microsoft technologies for creating distributed applications.
Open the Visual Studio and create a “New Project” and select the WCF option where various WCF applications can be created, here I want a service application and select that choice and name the application and click ok. On Successful project creation, now Visual studio gives us the option for automatic code sample.
Per the docs:
Only one InstanceContext object is used for all incoming calls and is not recycled subsequent to the calls. If a service object does not exist, one is created.
So there is only one instance, and it's not cleaned up after a call is made. This is like a Singleton for your WCF service. So you need to be careful about shared memory and resources.
To answer your question - yes, this is the way it works.
UPDATE Added sample:
I modified a few samples from MSDN to show the effects of InstanceContextMode.Single
. You'll see the operation count will continue to increment even though I use two different clients. If I change the InstanceContextMode
to PerCall
, the count will be different (it will be zero).
self-hosted service:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class CalculatorService : ICalculatorInstance
{
static Object syncObject = new object();
static int instanceCount;
int instanceId;
int operationCount;
public CalculatorService()
{
lock (syncObject)
{
instanceCount++;
instanceId = instanceCount;
}
}
public double Add(double n1, double n2)
{
operationCount++;
return n1 + n2;
}
public double Subtract(double n1, double n2)
{
Interlocked.Increment(ref operationCount);
return n1 - n2;
}
public double Multiply(double n1, double n2)
{
Interlocked.Increment(ref operationCount);
return n1 * n2;
}
public double Divide(double n1, double n2)
{
Interlocked.Increment(ref operationCount);
return n1 / n2;
}
public string GetInstanceContextMode()
{ // Return the InstanceContextMode of the service
ServiceHost host = (ServiceHost)OperationContext.Current.Host;
ServiceBehaviorAttribute behavior = host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
return behavior.InstanceContextMode.ToString();
}
public int GetInstanceId()
{ // Return the id for this instance
return instanceId;
}
public int GetOperationCount()
{ // Return the number of ICalculator operations performed
// on this instance
lock (syncObject)
{
return operationCount;
}
}
}
public class Program
{
static void Main(string[] args)
{
Uri baseAddress = new Uri("http://localhost:12345/calc");
using (ServiceHost host = new ServiceHost(typeof(CalculatorService), baseAddress))
{
// Enable metadata publishing.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
// Open the ServiceHost to start listening for messages. Since
// no endpoints are explicitly configured, the runtime will create
// one endpoint per base address for each service contract implemented
// by the service.
host.Open();
Console.WriteLine("The service is ready at {0}", baseAddress);
Console.WriteLine("Press <Enter> to stop the service.");
Console.ReadLine();
// Close the ServiceHost.
host.Close();
}
Console.WriteLine();
Console.WriteLine("Press <ENTER> to terminate client.");
Console.ReadLine();
}
}
client:
class Program
{
static void Main()
{
// Create a client.
CalculatorInstanceClient client = new CalculatorInstanceClient();
string instanceMode = client.GetInstanceContextMode();
Console.WriteLine("InstanceContextMode: {0}", instanceMode);
Console.WriteLine("client1's turn");
Console.WriteLine("2 + 2 = {0}", client.Add(2, 2).ToString());
Console.WriteLine("3 - 1 = {0}", client.Subtract(3, 1).ToString());
Console.WriteLine("number of operations = {0}", client.GetOperationCount().ToString());
// Create a second client.
CalculatorInstanceClient client2 = new CalculatorInstanceClient();
Console.WriteLine("client2's turn");
Console.WriteLine("2 + 2 = {0}", client2.Add(2, 2).ToString());
Console.WriteLine("3 - 1 = {0}", client2.Subtract(3, 1).ToString());
Console.WriteLine("number of operations = {0}", client2.GetOperationCount().ToString());
Console.WriteLine();
Console.WriteLine("Press <ENTER> to terminate client.");
Console.ReadLine();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With