2010-06-29 3 views
2

Mise à jour: avec l'aide de Henk, a déterminé que public Dispose() est appelé, qui appelle à son tour privé Dispose (true). C'est ma première implémentation de l'interface IDisposable, donc je ne sais pas si c'est correct. Je n'appelle pas Dispose explicitement n'importe où. Il semble que l'architecture WCF l'appelle à la sortie de chaque membre d'OperationsContract.Problème avec le service WCF avec des données statiques

A pris le code de nettoyage non géré sur Dispose for now, et plusieurs appels sont en mesure d'accéder aux données statiques. Il semble que Dispose() soit appelé sur tous les objets alloués localement au retour des appels, même s'il y a une référence à l'objet dans le stockage statique. Pas sûr dans. Net monde comment contourner cela afin que l'interface IDisposable sera callé correctement. Je devine que ces objets seront récupérés à un moment donné.

est ici pile d'appel au retour du 1er appel lorsque Dispose est appelé:

BossISeriesCwbxService.dll BossISeriesCwbxServices.DataContracts.ISeriesSystem.Dispose (bool bDisposing = true) Ligne 119 C#
BossISeriesCwbxService.dll! BossISeriesCwbxServices.DataContracts.ISeriesSystem.Dispose() ligne 107 + 0xd octets C#
System.ServiceModel.dll! System.ServiceModel.Dispatcher.MessageRpc.DisposeParametersCore() + 0x56 octets Syste m.ServiceModel.dll! System.ServiceModel.Dispatcher.MessageRpc.DisposeParameters() + 0xf octets System.ServiceModel.dll! System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessageCleanup (ref System.ServiceModel.Dispatcher.MessageRpc = rpc {System.ServiceModel.Dispatcher.MessageRpc}) + 0x135 octets System.ServiceModel.dll! System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5 (ref System.ServiceModel.Dispatcher.MessageRpc = rpc {System.ServiceModel.Dispatcher. MessageRpc}) + 0x1bf octets System.ServiceModel.dll! System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4 (réf System.ServiceModel.Dispatcher.MessageRpc rpc) + 0x80 octets
System.ServiceModel.dll! System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3 (ref System.ServiceModel.Dispatcher.MessageRpc rpc) + 0x36 octets
System.ServiceModel.dll! System.ServiceModel .Dispatcher.ImmutableDispatchRuntime.ProcessMessage2 (ref System.ServiceModel.Dispatcher.MessageRpc rpc) + 0x43 octets
System.ServiceModel.dll! System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1 (ref System.ServiceModel.Dispatcher.MessageRpc rpc) + 0xd7 octets
System.ServiceModel.dll! System.Serv iceModel.Dispatcher.MessageRpc.Process (bool isOperationContextSet = false) + 0x9B octets
System.ServiceModel.dll! System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Dispatch (ref System.ServiceModel.Dispatcher.MessageRpc rpc, bool isOperationContextSet) + 0x2D octets

System.ServiceModel.dll! System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump (System.ServiceModel.Channels.RequestContext demande = { System.ServiceModel.Security.SecuritySessionServerSettings.SecuritySessionRequestContext}, bool cleanThread, System.ServiceModel.OperationContext currentOperationContext) + 0x20c octets
System.ServiceModel.dll! System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest (System.ServiceModel.Channels.RequestContext demande, système .ServiceModel.OperationContext currentOperationContext) + 0xDF octets

System.ServiceModel.dll! System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump (System.IAsyncResult résultat) + 0x43 octets
System.ServiceModel.dll! System.Ser viceModel.Dispatcher.ChannelHandler.OnContinueAsyncReceive (objet état) + 0x45 octets
System.ServiceModel.dll! System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke2() + 0x46 octets System.ServiceModel.dll! système. ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.OnSecurityContextCallback (objet o) + 0x28 octets
mscorlib.dll! System.Security.SecurityContext.Run (System.Security.SecurityContext SecurityContext, System.Threading.ContextCallback rappel, état objet) + 0x55 octets

System.ServiceModel.dll! System.ServiceModel.Cha nnels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke() + 0x4D octets

System.ServiceModel.dll! System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ProcessCallbacks() + 0x180 octets System.ServiceModel.dll! système. ServiceModel.Channels.IOThreadScheduler.CriticalHelper.CompletionCallback (objet état) + 0x7a octets
System.ServiceModel.dll! System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ScheduledOverlapped.IOCallback (uint errorCode, numBytes uint, System.Threading .NativeOverlapped * nativeOverlapped) + 0xf octets
SMDiagnostics.dll! System.Serv iceModel.Diagnostics.Utility.IOCompletionThunk.UnhandledExceptionFrame (uint erreur, uint bytesRead, System.Threading.NativeOverlapped * nativeOverlapped) + 0x3D octets
mscorlib.dll! System.Threading._IOCompletionCallback.PerformIOCompletionCallback (uint errorCode, uint numBytes , System.Threading.NativeOverlapped * pOVERLAP) + 0x54 octets

J'ai lu quelques messages sur la mise en cache des données statiques dans une classe d'implémentation de service WCF, et avait un problème avec le GC appelant dispose sur les objets dans un static Dictionnaire. Je référencement des objets d'IBM iSeries activex Access, donc je mis en œuvre l'interface IDisposable pour nettoyer la connexion à l'iSeries. Mon problème est le GC est la disposition des objets dans les membres statiques de la classe Service. Je ne suis pas sûr que tout le code était nécessaire, mais ici c'est quand même. Le problème est que le retour de chaque méthode OperationContract, le GC appelle Dispose sur l'objet ISeriesSystem ou file d'attente qui a été ajouté au dictionnaire associé, mais le ISeriesSystem Dictionnaire est statique, donc je pense qu'il a tenu une référence à l'objet, de sorte GC ne serait pas fait jusqu'à ce qu'il soit retiré du dictionnaire.

service Interface:

[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);  
} 

Mise en œuvre du service:

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

Queue 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 ""; 
     } 
     } 
    } 
} 

Code client:

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); 

Service hébergé 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(); 

Répondre

0

Pouvez-vous mettre le code suivant:

[ServiceContract(SessionMode = SessionMode.Required)] 

sur votre contrat de service juste pour vous assurer que la session de transport est Étant créé? Si ce n'est pas le cas, cela devrait provoquer une erreur.

WSHttpBinding ne crée pas une session de transport sans sécurité et une session fiable.

EDIT:

Autre que cela, puisque vous créez un service Single Instance, pourquoi auriez-vous besoin des membres statiques? Il n'y aura qu'une seule instance en vie, donc tous les membres de cette instance vivront avec et seront un peu statiques. Avez-vous pensé à cela ou y a-t-il une raison spécifique d'utiliser des membres statiques?

+0

même comportement avec SessionMode.Champs obligatoires. Je ne suis pas lié à la liaison Http. En fait utilisera NetTcp si cela entre en production. –

1

Est-ce que cela arrive régulièrement ou de temps en temps? Cela arrive-t-il en développement ou seulement (après un certain temps) sur le serveur de production? Lorsque vous hébergez ce sous IIS, le serveur peut décider de «recycler» votre application. Conseil de base: n'utilisez pas static dans les applications serveur. Ce n'est pas fiable et pas évolutif.


Modifier
OK, je l'ai lu un peu plus (mais pas tous).

Le problème est que le retour de chaque méthode OperationContract, le GC appelle Éliminez le objet ISeriesSystem ou file d'attente

Vous devez vérifier que dans le détail. Est-ce vraiment le GC qui appelle votre Finalizer (s) (aka destructors)? Vous devez utiliser la journalisation ou le débogage pour vérifier que la surcharge Dispose (false) est appelée. Si Dispose (true) est appelé (et je vois beaucoup de code impliqué dans cela), vous devriez empiler trace à la cause réelle.

+0

Est un service de preuve de concept, pas en production. Se produit à chaque appel qui s'ajoute au dictionnaire statique. –

+0

Dispose (vrai) est appelé pile –

+0

trace: (ne me laisse pas coller la pile entière) > BossISeriesCwbxService.dll BossISeriesCwbxServices.DataContracts.ISeriesSystem.Dispose() Ligne 107 C# System.ServiceModel.dll System.ServiceModel!. Dispatcher.MessageRpc.DisposeParametersCore() + 0x56 octets System.ServiceModel.dll! System.ServiceModel.Dispatcher.MessageRpc.DisposeParameters() + 0xf octets –

0

Je sais que c'est un peu tard, mais avez-vous essayé d'ajouter l'attribut [OperationBehavior(AutoDisposeParameters = false)]?

Link to MSDN Forum

Questions connexes