Conceptually, the sessionful service instance management technique as described so far connects a client (or clients) to a service instance. Yet, the real picture is more complex. Recall from Chapter 1 that each service instance is hosted in a context, as shown in Figure 4-2.
What sessions actually do is correlate the client messages not to
the instance, but to the context that hosts it. When the session starts,
the host creates a new context. When the session ends, the context is
terminated. By default, the lifetime of the context is the same as that
of the instance it hosts. However, for optimization and extensibility
purposes, WCF provides the service designer with the option of
separating the two lifetimes and deactivating the instance separately
from its context. In fact, WCF also allows a context to exist without an
associated instance at all, as shown in Figure 4-2. I call this instance management
technique context deactivation. The common way of
controlling context deactivation is via the
ReleaseInstanceMode
property of the Operation
Behavior
attribute:
public enum ReleaseInstanceMode { None, BeforeCall, AfterCall, BeforeAndAfterCall, } [AttributeUsage(AttributeTargets.Method)] public sealed class OperationBehaviorAttribute : Attribute,... { public ReleaseInstanceMode ReleaseInstanceMode {get;set;} //More members }
ReleaseInstanceMode
is of the
enum type ReleaseInstanceMode
. The
various values of ReleaseInstanceMode
control when to release the instance in relation to the method call:
before, after, before and after, or not at all. When releasing the
instance, if the service supports IDisposable
, the
Dispose()
method is called and
Dispose()
has an operation
context.
You typically apply instance deactivation on some but not all service methods, or with different values on different methods:
[ServiceContract(SessionMode = SessionMode.Required)]
interface IMyContract
{
[OperationContract]
void MyMethod();
[OperationContract]
void MyOtherMethod();
}
class MyService : IMyContract,IDisposable
{
[OperationBehavior(ReleaseInstanceMode = ReleaseInstanceMode.AfterCall
)]
public void MyMethod()
{...}
public void MyOtherMethod()
{...}
public void Dispose()
{...}
}
The reason you typically apply it sporadically is that if you were to apply it uniformly, you would end up with a per-call-like service, in which case you might as well have configured the service as per-call.
If relying on instance deactivation assumes a certain call order, you can try to enforce that order using demarcating operations.
The default value for the ReleaseInstanceMode
property is ReleaseInstanceMode.None
, so these two
definitions are equivalent:
[OperationBehavior(ReleaseInstanceMode = ReleaseInstanceMode.None)] public void MyMethod() {...} public void MyMethod() {...}
ReleaseInstanceMode.None
means that the instance lifetime is not affected by the call, as shown
in Figure 4-3.
When a method is configured with ReleaseInstanceMode.BeforeCall
, if there is
already an instance in the session, before forwarding the call WCF
will deactivate it, create a new instance in its place, and let that
new instance service the call, as shown in Figure 4-4.
WCF deactivates the instance and calls Dispose()
before the call is done on the
incoming call thread, while the client blocks. This ensures that the
deactivation is indeed done before the call, not concurrently with it.
ReleaseInstanceMode.BeforeCall
is
designed to optimize methods such as Create()
that acquire some valuable
resources, yet wish to release the previously allocated resources.
Instead of acquiring the resources when the session starts, you wait
until the call to the Create()
method and then both release the previously allocated resources and
allocate new ones. After Create()
is called, you are ready to start calling other methods on the
instance, which are typically configured with ReleaseInstanceMode.None
.
When a method is configured with ReleaseInstanceMode.AfterCall
, WCF
deactivates the instance after the call, as shown in Figure 4-5.
This is designed to optimize a method such as Cleanup()
that cleans up valuable resources held by the instance, without
waiting for the session to terminate. Release
Instance
Mode.
AfterCall
is typically applied on
methods called after methods configured with Release
Instance
Mode.None
.
As its name implies,
configuring a method with ReleaseInstanceMode.Before
And
AfterCall
has the combined effect of using
ReleaseInstanceMode.BeforeCall
and
Release
Instance
Mode.
AfterCall
. If the context has an
instance before the call is made, just before the call WCF deactivates
that instance and creates a new instance to service the call. It then
deactivates the new instance after the call, as shown in Figure 4-6.
ReleaseInstanceMode.BeforeAndAfterCall
may
look superfluous at first glance, but it actually complements the
other values. It is designed to be applied on methods called after
methods marked with ReleaseInstanceMode.BeforeCall
or None
, or before
methods marked with ReleaseInstanceMode.AfterCall
or None
. Consider a situation where the
sessionful service wants to benefit from state-aware behavior (like a
per-call service), while holding onto resources only when needed to
optimize resource allocation and security lookup. If ReleaseInstanceMode.BeforeCall
were the only
available option, there would be a period of time after the call when
the resources would still be allocated to
the object, but would not be in use. A similar situation would occur
if Release
Instance
Mode.
AfterCall
were the only available option, because there would be
a period of time before the call when the resources would be
wasted.
Instead of making a design-time decision on which
methods to use to deactivate an instance, you can make a runtime
decision to deactivate the instance after the method returns. You do
that by calling the ReleaseServiceInstance()
method on the
instance context. You obtain the instance context via the InstanceContext
property of the operation context:
public sealed class InstanceContext : ... { public void ReleaseServiceInstance(); //More members } public sealed class OperationContext : ... { public InstanceContext InstanceContext {get;} //More members }
Example 4-8 demonstrates using explicit deactivation to implement a custom instance management technique that is dependent on the value of a counter.
Example 4-8. Using ReleaseServiceInstance()
[ServiceContract(SessionMode = SessionMode.Required)]
interface IMyContract
{
[OperationContract]
void MyMethod();
}
class MyService : IMyContract,IDisposable
{
int m_Counter = 0;
public void MyMethod()
{
m_Counter++;
if(m_Counter > 4)
{
OperationContext.Current.InstanceContext.ReleaseServiceInstance()
;
}
}
public void Dispose()
{...}
}
Calling ReleaseServiceInstance()
has a similar
effect to using ReleaseInstanceMode.AfterCall
. When used in
a method decorated with ReleaseInstanceMode.BeforeCall
, it has a
similar effect to using ReleaseInstanceMode.BeforeAndAfterCall
.
Note
Instance deactivation affects a singleton as well, although combining the two makes little sense—by its very definition, it is permissible and even desirable to never deactivate the singleton.
Instance deactivation is an optimization technique and, like all optimization techniques, you should avoid it in the general case. It adds complexity to the application and makes the code less approachable and maintainable to all but the WCF expert. Consider using instance deactivation only after failing to meet both your performance and scalability goals and when careful examination and profiling has proven beyond a doubt that using instance deactivation will improve the situation. If scalability and throughput are your concerns, you should take advantage of the simplicity of the per-call instancing mode and avoid instance deactivation. The main reason I share this technique with you is that WCF itself makes extensive use of instance deactivation; thus, knowledge of it is instrumental in demystifying other aspects of WCF, such as durable services and transactions.
Get Programming WCF Services, 3rd Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.