2008-11-07 10 views
2

L'une des causes fréquentes des fuites de mémoire dans .Net sont les gestionnaires d'événements qui ne sont jamais supprimés de leurs objets source.Est-ce que ce code côté client WCF provoquera une fuite de mémoire?

Ce code WCF provoquera-t-il une fuite de mémoire, ou le lambda sera-t-il également hors de portée, permettant à la fois la classe proxy et le gestionnaire d'être GCed?

void AMethod() 
{ 
    WCFClient proxy; 
    proxy = new WCFClient(); 
    proxy.RemoteOperationCompleted += (sender, e) => proxy.Close(); 
    proxy.Open(); 
    proxy.RemoteOperationAsync(); 
} 

Répondre

2

Voici mon test - notez l'ensemble proxy explicite à null dans le lambda - sans que cela les WeakReference vie et donc une fuite est susceptible:

public class Proxy 
{ 
    private bool _isOpen; 

    public event EventHandler Complete; 

    public void Close() 
    { 
     _isOpen = false; 
    } 

    public void Open() 
    { 
     _isOpen = true; 
    } 

    public void RemoteOperationAsync() 
    { 
     if (!_isOpen) 
      throw new ApplicationException(); 
     Thread.Sleep(1000); 
     if (Complete != null) 
      Complete(this, EventArgs.Empty); 
    } 
} 

public static class Program 
{ 
    public static void Main() 
    { 
     WeakReference wr = null; 

     { 
      var proxy = new Proxy(); 
      proxy.Complete += (sender, e) => 
       { 
        proxy.Close(); 
        wr = new WeakReference(proxy); 
        proxy = null; 
       }; 
      proxy.Open(); 
      proxy.RemoteOperationAsync(); 
     } 

     GC.Collect(GC.GetGeneration(wr)); 
     GC.WaitForPendingFinalizers(); 

     Console.WriteLine("[LAMBDA] Is WeakReference alive? " + wr.IsAlive); 
    } 
} 
-1

Cet objet va mourir ... il sera nettoyé.

N'oubliez pas que le lamda ne fait rien de spécial ... c'est une astuce de compilateur (donc supposons que c'est un + = SomeDelegate normal).

En outre, la méthode "Close" (je ne sais pas pourquoi ils ne l'ont pas rendue IDisposable) nettoiera tout ce qui reste ouvert.

1

N'oubliez pas que les proxy n'implémentent pas IDisposable correctement. Si une erreur se produit, le code ci-dessus ne nettoiera pas la connexion et le handle restera jusqu'à ce que le processus parent soit fermé.

0

Le contexte où le lamdba est défini sera capturé et la volonté donc "survivre" dans la classe de fermeture créée par le compilateur (vous pouvez les voir avec Reflector) - donc votre proxy aussi. Utilisez un gestionnaire d'événements faible ou écrivez du code pour l'annulation de l'enregistrement. Mais dans ce cas, vous ne pouvez pas utiliser l'expression lambda.