WCF服务-管理静态数据时出现问题.正在调用Dispose().

WCF服务-管理静态数据时出现问题.正在调用Dispose().

问题描述:

我在Service实现类中有一个WCF服务,该数据具有我DataContracts之一的对象的静态字典:

I have a WCF Service with static Dictonary of objects of one of my DataContracts in the Service implementation class:

[ServiceBehavior()]
public class DataQueueService : IDataQueueService
{


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



数据协定具有私有的非托管ActiveX对象(IBM iSeries Access,AS400System对象):



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

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


...
}


我已经使用从msdn文章中复制的标准实现来实现public Dispose()方法.我的问题是从每个OperationContract方法返回时都会调用Dispose().

我有一个OperationContract方法,该方法分配对象并将其添加到静态字典中:


...
}


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:

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





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





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];
}



和其他使用静态对象的OperationContract方法.这些对象在以后的调用中仍然存在,但是由于调用了Dispose(),因此清除了非托管ActiveX对象.

更新2010/7/1:我尝试切换到InstanceContextMode = Single并获得相同结果.

这是调用Dispose()的调用堆栈:



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:

>   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



通常,在WCF中,默认的实例管理是每次调用",因此,对于每个方法调用,dispose方法调用都将丢失所有值.

因此,最好查看一下WCF中的INSTANCEMANAGEMENT,然后选择适合您的一种.

WCF中的INSTANCEMANAGEMENT [< ahref target ="^ >]
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="^">]


如果WCF的实例管理对您不起作用,您可以创建另一个静态类来管理您的activeX对象吗?

http://en.wikipedia.org/wiki/Object_pool_pattern [
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[^]