Click here to Skip to main content
15,905,563 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a WCF Service with static Dictonary of objects of one of my DataContracts in the Service implementation class:

C#
[ServiceBehavior()]
public class DataQueueService : IDataQueueService
{

C#
private static Dictionary<string, ISeriesSystem> mdictISeriesSystems = new Dictionary<string, ISeriesSystem>();
public static IDictionary<string, ISeriesSystem> ISeriesDict
{
   get { return mdictISeriesSystems; }
}
...
}


The data contract has a private unmanaged ActiveX object (IBM iSeries Access, AS400System object):

C#
public class ISeriesSystem : IDisposable
{
<pre lang="cs">private cwbx.AS400System mcwbxISeriesSystem = new AS400System();
private cwbx.AS400System CwbxISeriesSystem
{
   get { return mcwbxISeriesSystem; }
   set { mcwbxISeriesSystem = value; }
}

...
}


I have implemented public Dispose() method using standard implementation copied from msdn article. My problem is that Dispose() is being called on return from each OperationContract method.

I have one OperationContract method that allocates objects and adds them to static Dictionary:

VB
[ServiceContract(Namespace = "BossISeriesCwbxServices")]
public interface IDataQueueService
{
   [OperationContract]
   ISeriesSystem SystemInitialize(string sISeriesName);
...
}


SQL
public ISeriesSystem SystemInitialize(string sISeriesName)
{
   return  AddSystem(sISeriesName);
}


C#
ISeriesSystem AddSystem(string sISeriesName)
{
   //ISeriesSystem oISeriesSystem = null;
   string sISeriesKey = sISeriesName.Trim();

   if (!DataQueueService.ISeriesDict.TryGetValue(sISeriesKey, out oISeriesSystem))
   {
      //oISeriesSystem = new ISeriesSystem(sISeriesName);
      DataQueueService.ISeriesDict[sISeriesKey] = new ISeriesSystem(sISeriesName);
   }

   //return oISeriesSystem;
   return DataQueueService.ISeriesDict[sISeriesKey];
}


And other OperationContract methods that use the static objects. The objects still exist on subsequent calls, but since Dispose() was called, the unmanaged ActiveX object was cleaned up.

Update 2010/7/1: I have tried switching to InstanceContextMode=Single with same results.

Here is the call stack from where Dispose() is called:

MSIL
>   BossISeriesCwbxService.dll!BossISeriesCwbxServices.DataContracts.ISeriesSystem.Dispose() Line 107   C#
    System.ServiceModel.dll!System.ServiceModel.Dispatcher.MessageRpc.DisposeParametersCore() + 0x56 bytes
    System.ServiceModel.dll!System.ServiceModel.Dispatcher.MessageRpc.DisposeParameters() + 0xf bytes
    System.ServiceModel.dll!System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessageCleanup(ref System.ServiceModel.Dispatcher.MessageRpc rpc = {System.ServiceModel.Dispatcher.MessageRpc}) + 0x135 bytes
    System.ServiceModel.dll!System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(ref System.ServiceModel.Dispatcher.MessageRpc rpc = {System.ServiceModel.Dispatcher.MessageRpc}) + 0x1bf bytes
    System.ServiceModel.dll!System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(ref System.ServiceModel.Dispatcher.MessageRpc rpc) + 0x80 bytes
    System.ServiceModel.dll!System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(ref System.ServiceModel.Dispatcher.MessageRpc rpc) + 0x36 bytes
    System.ServiceModel.dll!System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(ref System.ServiceModel.Dispatcher.MessageRpc rpc) + 0x43 bytes
    System.ServiceModel.dll!System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(ref System.ServiceModel.Dispatcher.MessageRpc rpc) + 0xd7 bytes
    System.ServiceModel.dll!System.ServiceModel.Dispatcher.MessageRpc.Process(bool isOperationContextSet = false) + 0x9b bytes
    System.ServiceModel.dll!System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Dispatch(ref System.ServiceModel.Dispatcher.MessageRpc rpc, bool isOperationContextSet) + 0x2d bytes
    System.ServiceModel.dll!System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(System.ServiceModel.Channels.RequestContext request = {System.ServiceModel.Security.SecuritySessionServerSettings.SecuritySessionRequestContext}, bool cleanThread, System.ServiceModel.OperationContext currentOperationContext) + 0x20c bytes
    System.ServiceModel.dll!System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(System.ServiceModel.Channels.RequestContext request, System.ServiceModel.OperationContext currentOperationContext) + 0xdf bytes
    System.ServiceModel.dll!System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(System.IAsyncResult result) + 0x43 bytes
    System.ServiceModel.dll!System.ServiceModel.Dispatcher.ChannelHandler.OnContinueAsyncReceive(object state) + 0x45 bytes
    System.ServiceModel.dll!System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke2() + 0x46 bytes
    System.ServiceModel.dll!System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.OnSecurityContextCallback(object o) + 0x28 bytes
    mscorlib.dll!System.Security.SecurityContext.Run(System.Security.SecurityContext securityContext, System.Threading.ContextCallback callback, object state) + 0x55 bytes
    System.ServiceModel.dll!System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke() + 0x4d bytes
    System.ServiceModel.dll!System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ProcessCallbacks() + 0x180 bytes
    System.ServiceModel.dll!System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.CompletionCallback(object state) + 0x7a bytes
    System.ServiceModel.dll!System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ScheduledOverlapped.IOCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* nativeOverlapped) + 0xf bytes
    SMDiagnostics.dll!System.ServiceModel.Diagnostics.Utility.IOCompletionThunk.UnhandledExceptionFrame(uint error, uint bytesRead, System.Threading.NativeOverlapped* nativeOverlapped) + 0x3d bytes
    mscorlib.dll!System.Threading._IOCompletionCallback.PerformIOCompletionCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* pOVERLAP) + 0x54 bytes
Posted
Updated 1-Jul-10 2:33am
v3

Hi.

Generally in WCF the default instancemanagement is Per-Call so that for every method call the dispose method call you are going to loss all the values.

So better have a look at INSTANCEMANAGEMENT IN WCF and choose the one which suits you.

INSTANCEMANAGEMENT IN WCF[<ahref target="^">]
 
Share this answer
 
v2
Comments
app1dak 1-Jul-10 8:37am    
Are you talking about switching the InstanceContextMode? I have tried InstanceContextMode=Single, with same results. Do I need to do something else to get a singleton service instance? Do I need to move the static data into a singleton class of it's own. I tried that also, but may not have implemented properlty. Dispose was still called.
Martin Jarvis 1-Jul-10 20:47pm    
The link above is broken, it should be: http://msdn.microsoft.com/hi-in/magazine/cc163590%28en-us%29.aspx
If the instance management of WCF isn't working for you, can you create another static class to manage your activeX objects?

http://en.wikipedia.org/wiki/Object_pool_pattern[^]
 
Share this answer
 
Comments
app1dak 2-Jul-10 10:00am    
So I have a c#.net System object that contains an IBM activex AS400System object. The activex object can't be created until the first client needing that system makes a call to WCF service. Do I create a pool of the .net System objects without the AS400System initializsed and cache them. Then, when 1st client makes call needing a specific AS400System object, at that time do the expensive initialization?

BTW, thanks for the idea.
Martin Jarvis 2-Jul-10 10:13am    
Yes pretty much.

With object pools you pretty much instance new implementations on demand, for example connection strings are pooled with instances being taken from the pool (on Open()) and then returned for reuse (on Close()).

If more than one object is required at the same time, then another object is created.

When the objects are no longer in use, the pool keeps them alive for a set period and if they're not used then the object is disposed to save resources.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900