2010-06-29 3 views
2

Обновление: при помощи Henk определено, что вызывается public Dispose(), который в свою очередь вызывает private Dispose (true). Это моя первая реализация интерфейса IDisposable, поэтому не уверен, что это правильно. Я не называю Dispose явно нигде. Кажется, что архитектура WCF вызывает ее при выходе из каждого члена OperationContract.Проблема с WCF Service со статическими данными

Взял неуправляемый код очистки из Dispose на данный момент, и несколько вызовов могут получить доступ к статическим данным. Кажется, что Dispose() вызывается для всех локально выделенных объектов при возврате из вызовов, даже если есть ссылка на объект в статическом хранилище. Не уверен в мире .net, как обойти это, чтобы правильно обработать IDisposable-интерфейс. Я предполагаю, что эти объекты также получат сбор мусора.

Вот стек вызовов по возвращении из 1-го вызова при Dispose вызывается:

BossISeriesCwbxService.dll BossISeriesCwbxServices.DataContracts.ISeriesSystem.Dispose (BOOL bDisposing = истина) Линия 119 C#
BossISeriesCwbxService.dll! BossISeriesCwbxServices.DataContracts.ISeriesSystem.Dispose() линия 107 + 0xD байт C#
System.ServiceModel.Dispatcher.MessageRpc.DisposeParametersCore() System.ServiceModel.dll! + 0x56 байт Syste m.ServiceModel.dll! System.ServiceModel.Dispatcher.MessageRpc.DisposeParameters() + 0xf байт System.ServiceModel.dll! System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessageCleanup (ссылка System.ServiceModel.Dispatcher.MessageRpc = RPC {} System.ServiceModel.Dispatcher.MessageRpc) + 0x135 байт System.ServiceModel.dll! System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5 (ссылка 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 байт
System.ServiceModel.dll! System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3 (ссылка System.ServiceModel.Dispatcher.MessageRpc RPC) + 0x36 байт
System.ServiceModel.dll! System.ServiceModel .Dispatcher.ImmutableDispatchRuntime.ProcessMessage2 (ссылка System.ServiceModel.Dispatcher.MessageRpc RPC) + 0x43 байт
System.ServiceModel.dll! System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1 (ссылка System.ServiceModel.Dispatcher.MessageRpc rpc) + 0xd7 bytes
System.ServiceModel.dll! System.Serv iceModel.Dispatcher.MessageRpc.Process (BOOL isOperationContextSet = ложь) + 0x9b байт
System.ServiceModel.dll! System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Dispatch (ссылка System.ServiceModel.Dispatcher.MessageRpc RPC, BOOL isOperationContextSet) + 0x2d байт

System.ServiceModel.dll! System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump (System.ServiceModel.Channels.RequestContext запрос = {System.ServiceModel.Security.SecuritySessionServerSettings.SecuritySessionRequestContext}, BOOL cleanThread, System.ServiceModel.OperationContext currentOperationContext) + 0x20c байт
System.ServiceModel.dll! System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest (System.ServiceModel.Channels.RequestContext запрос, система .ServiceModel.OperationContext currentOperationContext) + 0xDF байт

System.ServiceModel.dll! System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump (System.IAsyncResult результат) + 0x43 байт
System.ServiceModel.dll! System.Ser viceModel.Dispatcher.ChannelHandler.OnContinueAsyncReceive (объект состояние) + 0x45 байт
System.ServiceModel.dll! System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke2() + 0x46 байт System.ServiceModel.dll! System. ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.OnSecurityContextCallback (объект о) + 0x28 байт
mscorlib.dll! System.Security.SecurityContext.Run (System.Security.SecurityContext SecurityContext, System.Threading.ContextCallback обратного вызова, состояние объекта) + 0x55 байт

System.ServiceModel.dll! System.ServiceModel.Cha nnels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke() + 0x4d байт

System.ServiceModel.dll! System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ProcessCallbacks() + 0x180 байт System.ServiceModel.dll! System. ServiceModel.Channels.IOThreadScheduler.CriticalHelper.CompletionCallback (объект состояние) + 0x7A байт
System.ServiceModel.dll! System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ScheduledOverlapped.IOCallback (UINT ERRORCODE, UINT numBytes, System.Threading .NativeOverlapped * nativeOverlapped) + 0xf bytes
SMDiagnostics.dll! System.Serv iceModel.Diagnostics.Utility.IOCompletionThunk.UnhandledExceptionFrame (UINT ошибка, UINT BytesRead, System.Threading.NativeOverlapped * NativeOverlapped) + 0x3d байт
mscorlib.dll! System.Threading._IOCompletionCallback.PerformIOCompletionCallback (UINT ERRORCODE, UINT numBytes , System.Threading.NativeOverlapped * pOVERLAP) + 0x54 байт

Я прочитал несколько постов на кэширование статических данных в классе реализации WCF службы, и была проблема с GC вызывающему выбрасывайте на объекты в статический словарь. Я ссылаюсь на некоторые объекты activex из IBM iSeries Access, поэтому я реализовал интерфейс IDisposable для очистки соединения с iSeries. Моя проблема - это GC is Disposing объектов в элементах Static класса Service. Не уверен, что весь код нужен, но здесь все равно. Проблема в том, что при возврате из каждого метода OperationContract GC вызывает Dispose в объекте ISeriesSystem или Queue, который был добавлен в соответствующий словарь, но словарь ISeriesSystem является статическим, поэтому я думал, что он содержит ссылку на объект, поэтому GC не будет выполняться до тех пор, пока он не будет удален из Словаря.

служба Интерфейс:

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

    [OperationContract(Name="FinalizeSystemByName")] 
    void SystemFinalize(string sISeriesName); 

    [OperationContract] 
    void SystemFinalize(ISeriesSystem oISeriesSystem); 

    [OperationContract] 
    Queue QueueInitialize(string sQueueName, string sLibrary, string sISeriesName); 

    [OperationContract(Name="FinalizeQueueByName")] 
    void QueueFinalize(string sQueueName, string sLibrary, string sISeriesName); 

    [OperationContract] 
    void QueueFinalize(Queue oDataQueue); 

    [OperationContract (Name="QueueWriteByName")] 
    void QueueWrite(string sQueueName, string sLibrary, string sISeriesName, string sMessage); 

    [OperationContract] 
    void QueueWrite(Queue oDataQueue, string sMessage); 

    [OperationContract (Name="QueueReadByName")] 
    string QueueRead(string sQueueName, string sLibrary, string sISeriesName); 

    [OperationContract] 
    string QueueRead(Queue oDataQueue);  
} 

Услуги по внедрению:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)] 
public class DataQueueService : IDataQueueService 
{ 
    private static Dictionary<string, ISeriesSystem> mdictISeriesSystems = new Dictionary<string, ISeriesSystem>(); 
    public static IDictionary<string, ISeriesSystem> ISeriesDict 
    { 
     get { return mdictISeriesSystems; } 
    } 

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

    public void SystemFinalize(string sISeriesName) 
    { 
    } 

    public void SystemFinalize(ISeriesSystem oISeriesSystem) 
    { 
    SystemFinalize(oISeriesSystem.Name); 
    } 


    public Queue QueueInitialize(string sQueueName, string sLibrary, string sISeriesName) 
    { 
    ISeriesSystem oISeriesSystem = null; 
    Queue oDataQueue = null; 

    try 
    { 
     oISeriesSystem = AddSystem(sISeriesName); 
     oDataQueue = oISeriesSystem.AddQueue(sQueueName, sLibrary); 
    } 
    catch (Exception ex) 
    { 
     // ToDo: Log ex to WCF service log and remove from Console. 
     Console.WriteLine(ex.ToString()); 
     oDataQueue = null; 
    } 

    return oDataQueue; 
    } 

    public Queue QueueInitialize(string sQueueName, string sLibrary, ISeriesSystem oISeriesSystem) 
    { 
    return QueueInitialize(sQueueName, sLibrary, oISeriesSystem.Name); 
    } 

    public void QueueFinalize(string sQueueName, string sLibrary, string sISeriesName) 
    { 
    string sISeriesKey = sISeriesName.Trim(); 
    string sDataQueueKey = sLibrary.Trim() + sQueueName.Trim(); 

    ISeriesSystem oISeriesSystem = null; 
    Queue oDataQueue = null; 


    if (DataQueueService.ISeriesDict.TryGetValue(sISeriesKey, out oISeriesSystem)) 
    { 
     if (oISeriesSystem.DataQueueDict.TryGetValue(sDataQueueKey, out oDataQueue)) 
     { 
      oDataQueue.Dispose(); 
      oDataQueue = null; 
      oISeriesSystem.DataQueueDict.Remove(sDataQueueKey); 
     } 

     if (oISeriesSystem.DataQueueDict.Count == 0) 
     { 
      oISeriesSystem.Dispose(); 
      oISeriesSystem = null; 
     } 
    } 
    } 

    public void QueueFinalize(Queue oDataQueue) 
    { 
    QueueFinalize(oDataQueue.Name, oDataQueue.Library, oDataQueue.ISeriesName); 
    } 

    public void QueueWrite(string sQueueName, string sLibrary, string sISeriesName, string sMessage) 
    { 
    string sISeriesKey = sISeriesName.Trim(); 
    string sDataQueueKey = sLibrary.Trim() + sQueueName.Trim(); 

    ISeriesSystem oISeriesSystem = null; 
    Queue oDataQueue = null; 


    if (DataQueueService.ISeriesDict.TryGetValue(sISeriesKey, out oISeriesSystem)) 
    { 
     if (oISeriesSystem.DataQueueDict.TryGetValue(sDataQueueKey, out oDataQueue)) 
     { 
      oDataQueue.Write(sMessage); 
     } 
    } 
    } 

    public void QueueWrite(Queue oDataQueue, string sMessage) 
    { 
    QueueWrite(oDataQueue.Name, oDataQueue.Library, oDataQueue.ISeriesName, sMessage); 
    } 

    public string QueueRead(string sQueueName, string sLibrary, string sISeriesName) 
    { 
    string sISeriesKey = sISeriesName.Trim(); 
    string sDataQueueKey = sLibrary.Trim() + sQueueName.Trim(); 

    ISeriesSystem oISeriesSystem = null; 
    Queue oDataQueue = null; 


    if (DataQueueService.ISeriesDict.TryGetValue(sISeriesKey, out oISeriesSystem)) 
    { 
     if (oISeriesSystem.DataQueueDict.TryGetValue(sDataQueueKey, out oDataQueue)) 
     { 
      return oDataQueue.Read(); 
     } 
    } 

    return ""; 
    } 

    public string QueueRead(Queue oDataQueue) 
    { 
    return QueueRead(oDataQueue.Name, oDataQueue.Library, oDataQueue.ISeriesName); 

    } 

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

    return oISeriesSystem; 
    } 

ISeriesSystem DataContract:

using System; 
using System.Collections.Generic; 
using System.Text; 

using System.ServiceModel; 
using System.Runtime.Serialization; 

using cwbx; 

namespace BossISeriesCwbxServices.DataContracts 
{ 
    public class ISeriesSystem : IDisposable 
    { 

     private string msName; 
     [DataMember] 
     public string Name 
     { 
     get { return msName; } 
     set { msName = value; } 
     } 

     private Dictionary<string, Queue> mdictDataQueues = new Dictionary<string, Queue>(); 
     public IDictionary<string, Queue> DataQueueDict 
     { 
     get { return mdictDataQueues; } 
     } 

     private cwbx.AS400System mcwbxISeriesSystem = new AS400System(); 
     private cwbx.AS400System CwbxISeriesSystem 
     { 
     get { return mcwbxISeriesSystem; } 
     set { mcwbxISeriesSystem = value; } 
     } 


     private bool bDisposed = false; 


     public ISeriesSystem() 
     { 

     } 

     public ISeriesSystem(string sISeriesName) 
     { 
     try 
     { 
      // Set DataContract properties. 
      this.Name = sISeriesName; 

      // Connect to iSeries, Logon and connect to iSeries services that may be used. 
      this.CwbxISeriesSystem.Define(sISeriesName); 
      this.CwbxISeriesSystem.UserID = "APP1DAK"; 
      this.CwbxISeriesSystem.Password = "DONNA99"; 
      this.CwbxISeriesSystem.Signon(); 
      this.CwbxISeriesSystem.Connect(cwbcoServiceEnum.cwbcoServiceDataQueues); 
      this.CwbxISeriesSystem.Connect(cwbcoServiceEnum.cwbcoServiceSecurity); 
      this.CwbxISeriesSystem.Connect(cwbcoServiceEnum.cwbcoServiceRemoteCmd); 
     } 
     catch (Exception ex) 
     { 
      // ToDo: Log ex to WCF service log and remove from Console. 
      Console.WriteLine(ex.ToString()); 
      foreach (cwbx.Error cwbxError in this.CwbxISeriesSystem.Errors) 
      { 
       Console.WriteLine(cwbxError.Text); 
       Console.WriteLine(cwbxError.ToString()); 
      } 
     } 
     } 

     ~ISeriesSystem() 
     { 
     Dispose(false); 
     } 

     public void Dispose() 
     { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
     } 

     private void Dispose(bool bDisposing) 
     { 
     // Only Dispose of the object 1 time. 
     if (!this.bDisposed) 
     { 
      // If disposing equals true, Dispose() was called by GC, so dispose all managed resources. 
      if (bDisposing) 
      { 
       // Dispose managed resources, calling object Dispose method for objects 
       // that implement IDisposable interface. 
      } 

      try 
      { 
       if (this.CwbxISeriesSystem.IsConnected(cwbcoServiceEnum.cwbcoServiceAny) == 1) 
       { 
        this.CwbxISeriesSystem.Disconnect(cwbcoServiceEnum.cwbcoServiceAll); 
       } 
      } 
      catch (Exception ex) 
      { 
       // ToDo: Log ex to WCF service log and remove from Console. 
       Console.WriteLine(ex.ToString()); 
       foreach (cwbx.Error cwbxError in this.CwbxISeriesSystem.Errors) 
       { 
        Console.WriteLine(cwbxError.Text); 
        Console.WriteLine(cwbxError.ToString()); 
       } 
      } 

      // Mark disposing as being done. 
      bDisposed = true; 
     } 
     } 

     public Queue AddQueue(string sQueueName, string sLibrary) 
     { 
     Queue oDataQueue = null; 
     string sDataQueueKey = sLibrary.Trim() + sQueueName.Trim(); 

     if (!this.DataQueueDict.TryGetValue(sDataQueueKey, out oDataQueue)) 
     { 
      oDataQueue = new Queue(sQueueName, sLibrary, this.CwbxISeriesSystem); 
      this.DataQueueDict[sDataQueueKey] = oDataQueue; 
     } 

     return oDataQueue; 
     } 
    } 
} 

Очередь DataContract:

using System; 
using System.Collections.Generic; 
using System.Text; 

using System.ServiceModel; 
using System.Runtime.Serialization; 

using cwbx; 

namespace BossISeriesCwbxServices.DataContracts 
{ 
    [DataContract] 
    public class Queue : IDisposable 
    { 
     private string msName; 
     [DataMember] 
     public string Name 
     { 
     get { return msName; } 
     set { msName = value; } 
     } 

     private string msLibrary; 
     [DataMember] 
     public string Library 
     { 
     get { return msLibrary; } 
     set { msLibrary = value; } 
     } 

     private string msISeriesName; 
     [DataMember] 
     public string ISeriesName 
     { 
     get { return msISeriesName; } 
     set { msISeriesName = value; } 
     } 

     private short miWaitTime = 10; 
     [DataMember] 
     public short WaitTime 
     { 
     get { return miWaitTime; } 
     set { miWaitTime = value; } 
     } 

     private short miNumberOfAttempts = 1; 
     [DataMember] 
     public short NumberOfAttempts 
     { 
     get { return miNumberOfAttempts; } 
     set { miNumberOfAttempts = value; } 
     } 

     private short miMaxQueueIndex = 1; 
     public short MaxQueueIndex 
     { 
     get { return miMaxQueueIndex; } 
     set { miMaxQueueIndex = value; } 
     } 

     private short miCurrentQueueIndex = 1; 
     public short CurrentQueueIndex 
     { 
     get { return miCurrentQueueIndex; } 
     set { miCurrentQueueIndex = value; } 
     } 



     private cwbx.DataQueue mcwbxDataQueue = new cwbx.DataQueue(); 
     private cwbx.DataQueue CwbxDataQueue 
     { 
     get { return mcwbxDataQueue; } 
     set { mcwbxDataQueue = value; } 
     } 

     private bool bDisposed = false; 


     public Queue() 
     { 
     } 

     public Queue(string sQueueName, string sLibrary, cwbx.AS400System cwbxISeriesSystem) 
     { 
     this.Name = sQueueName; 
     this.Library = sLibrary; 
     this.ISeriesName = cwbxISeriesSystem.SystemName; 

     this.CwbxDataQueue.QueueName = sQueueName; 
     this.CwbxDataQueue.LibraryName = sLibrary; 
     this.CwbxDataQueue.system = cwbxISeriesSystem; 
     } 

     ~Queue() 
     { 
     Dispose(false); 
     } 

     public void Dispose() 
     { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
     } 

     private void Dispose(bool bDisposing) 
     { 
     // Only Dispose of the object 1 time. 
     if (!this.bDisposed) 
     { 
      // If disposing equals true, Dispose() was called by GC, so dispose all managed resources. 
      if (bDisposing) 
      { 
       // Dispose managed resources, calling object Dispose method for objects 
       // that implement IDisposable interface. 
      } 

      // Call the appropriate methods to clean up unmanaged resources here. 
      try 
      { 
       this.CwbxDataQueue = null; 
      } 
      catch (Exception ex) 
      { 
       // ToDo: Log ex to WCF service log and remove from Console. 
       Console.WriteLine(ex.ToString()); 
       foreach (cwbx.Error cwbxError in this.CwbxDataQueue.Errors) 
       { 
        Console.WriteLine(cwbxError.Text); 
        Console.WriteLine(cwbxError.ToString()); 
       } 
      } 
      // Mark disposing as being done. 
      bDisposed = true; 
     } 
     } 


     public void Write(string sMessage) 
     { 
     try 
     { 
      cwbx.StringConverter cwbxStringConverter = new cwbx.StringConverter(); 
      Object oBytes = cwbxStringConverter.ToBytes(sMessage); 
      this.CwbxDataQueue.Write(oBytes, false); 
     } 
     catch (Exception ex) 
     { 
      // ToDo: Log ex to WCF service log and remove from Console. 
      Console.WriteLine(ex.ToString()); 
      foreach (cwbx.Error cwbxError in this.CwbxDataQueue.Errors) 
      { 
       Console.WriteLine(cwbxError.Text); 
       Console.WriteLine(cwbxError.ToString()); 
      } 
     } 
     } 

     public string Read() 
     { 
     try 
     { 
      Object oObject = null; 
      return (new cwbx.StringConverter()).FromBytes(this.CwbxDataQueue.Read(this.WaitTime * this.NumberOfAttempts, out oObject)); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.ToString()); 
      foreach (cwbx.Error cwbxError in this.CwbxDataQueue.Errors) 
      { 
       Console.WriteLine(cwbxError.Text); 
       Console.WriteLine(cwbxError.ToString()); 
      } 

      return ""; 
     } 
     } 
    } 
} 
Код

Клиент:

ISeriesSystem oISeriesSystem = null; 
Queue oDataQueue = null; 

oISeriesSystem = DQService.SystemInitialize("A2029D2.AS400.US.UPS.COM"); 
oDataQueue = DQService.QueueInitialize("SMTLST020", "IB5EXE", oISeriesSystem.Name); 
oISeriesSystem.DataQueueDict.Add(oDataQueue.Library + oDataQueue.Name, oDataQueue); 
ISeriesSystemDict.Add(oISeriesSystem.Name, oISeriesSystem); 

DQService.QueueWrite(oDataQueue, "Testing cwbx.DataQueue WCF service"); 
string sMessage = DQService.QueueRead(oDataQueue); 

Exe Хостинг Услуги:

Uri baseAddress = new Uri("http://localhost:8080/BossISeriesCwbxServices"); 

//Instantiate new ServiceHost 
moServiceHost = new ServiceHost(typeof(BossISeriesCwbxServices.DataQueueService), baseAddress); 

// Add Endpoint 
moServiceHost.AddServiceEndpoint(typeof(BossISeriesCwbxServices.IDataQueueService), new WSHttpBinding(), "IDataQueueService"); 
// Enable metadata exchange. 
ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); 
smb.HttpGetEnabled = true; 
moServiceHost.Description.Behaviors.Add(smb); 

//Open moServiceHost 
moServiceHost.Open(); 
Console.WriteLine("The IDataQueueService is ready."); 
Console.WriteLine("Press <ENTER> to terminate service."); 
Console.WriteLine(); 

ответ

0

Вы можете поместить следующий код:

[ServiceContract(SessionMode = SessionMode.Required)] 

на ваш контракт на обслуживание только чтобы убедиться, что транспортная сессия создается? Если это не так, это должно вызвать ошибку.

WSHttpBinding не создает сеанс транспорта без обеспечения безопасности и надежной сессии.

EDIT:

Кроме этого, так как вы создаете Single Instance сервис, зачем вам статические члены? Будет только один экземпляр живой, поэтому любые члены экземпляра этого экземпляра будут жить с ним и будут выглядеть как статические. Вы думали об этом или есть конкретная причина использования статических членов?

+0

такое же поведение с SessionMode.Необходимые. Я не привязан к привязке Http. На самом деле будет использовать NetTcp, если это произойдет в производстве. –

1

Случается ли это регулярно или время от времени? Это происходит в процессе разработки или только (через некоторое время) на производственном сервере?

Когда вы размещаете это под IIS, сервер может решить «переработать» ваше приложение. Базовый совет: не используйте static в серверных приложениях. Он не является надежным и не масштабируемым.


Редактировать
ОК, я прочитал немного больше (но не все).

Проблема заключается в том, что по возвращении из каждого метода OperationContract ГХ призывает Dispose на ISeriesSystem или очереди объекта

Вы должны убедиться, что в деталях. Это действительно GC, который называет ваш Finalizer (s) (aka destructors)? Вы должны использовать ведение журнала или отладки, чтобы убедиться, что вызывается перегрузка Dispose (false). Если Dispose (true) вызывается (и я вижу много кода, участвующего в этом), вы должны установить stacktrace в фактическую причину.

+0

Является доказательством концепции обслуживания, а не в производстве. Происходит при каждом вызове, который добавляется к Статическому словарю. –

+0

Dispose (истина) называется –

+0

трассировки стека: (не позволит мне вставить весь стек) > BossISeriesCwbxService.dll BossISeriesCwbxServices.DataContracts.ISeriesSystem.Dispose() Строка 107 C# System.ServiceModel.dll System.ServiceModel!. Dispatcher.MessageRpc.DisposeParametersCore() + 0x56 bytes System.ServiceModel.dll! System.ServiceModel.Dispatcher.MessageRpc.DisposeParameters() + 0xf bytes –

0

Я знаю, что немного поздно, но вы попробовали добавить атрибут [OperationBehavior(AutoDisposeParameters = false)]?

Link to MSDN Forum

Смежные вопросы