3 votes

Fuite de mémoire sur BeginInvoke

1) J'ai entendu dire que si nous n'appelons pas EndInvoke(), cela peut entraîner une fuite de mémoire. Pouvez-vous nous démontrer comment cela peut entraîner une fuite de mémoire ?

2) Lorsque je dois appeler EndInvoke(), dois-je utiliser le code suivant ?

namespace BlockMechanism
{
    public delegate int MyDelegate(List<int> someInts);
    class MainClass
    {
        static void Main()
        {
           List<int> someInts = new List<int> { 1, 2, 3, 4, 5, 6, 7 };
           MyDelegate test = FinalResult;
           IAsyncResult res=test.BeginInvoke(someInts, null, test);
           Console.WriteLine(test.EndInvoke(res));
           Console.ReadKey(true);
        }

        public static int FinalResult(List<int> Mylist)
        {
            return Mylist.Sum();
        }

    }
}

4voto

Darin Dimitrov Points 528142

Bien que votre exemple soit correct, il n'y a aucun avantage à utiliser un thread différent parce que vous appelez EndInvoke sur le thread principal qui bloquera jusqu'à ce que l'opération soit terminée et qu'il ne puisse plus effectuer d'autres tâches. Il aurait été équivalent d'appeler Invoke sur le délégué ou directement le FinalResult elle-même. Habituellement, EndInvoke est appelé dans le callback fourni par le BeginInvoke méthode :

class Program
{
    public delegate int MyDelegate(List<int> someInts);
    class MainClass
    {
        static void Main()
        {
            List<int> someInts = new List<int> { 1, 2, 3, 4, 5, 6, 7 };
            MyDelegate test = FinalResult;
            test.BeginInvoke(someInts, ar => 
            {
                MyDelegate del = (MyDelegate)ar.AsyncState;
                Console.WriteLine(del.EndInvoke(ar));
            }, test);
            Console.ReadKey(true);
        }

        public static int FinalResult(List<int> Mylist)
        {
            return Mylist.Sum();
        }
    }
}

En ce qui concerne la fuite de mémoire, vous pouvez jeter un coup d'oeil à ceci filetage .

P.S : Les membres de l'instance de l Liste<T> ne sont pas thread safe, vous devez donc faire attention lorsque vous y accédez depuis plusieurs threads.

2voto

Kevin Montrose Points 11936

Article de MSDN sur Begin/EndInvoke()

En gros, si vous n'appelez pas EndInvoke() vous courez le risque d'une fuite quelque chose . Généralement, il s'agit soit de la mémoire, soit d'un fil bloqué pour toujours dans un pool quelque part.

L'article aborde quatre façons courantes d'utiliser BeginInvoke() et quand vous devez appeler EndInvoke() pour chacun.

Pour la postérité, je les reproduis ici :

  • Effectuez un travail, puis appelez EndInvoke pour bloquer jusqu'à ce que l'appel soit terminé.

  • Obtenez un WaitHandle à l'aide de la propriété System.IAsyncResult.AsyncWaitHandle, utilisez sa méthode WaitOne pour bloquer l'exécution jusqu'à ce que le WaitHandle soit signalé, puis appelez EndInvoke.

  • Interroge le IAsyncResult renvoyé par BeginInvoke pour déterminer quand l'appel asynchrone est terminé, puis appelle EndInvoke.

  • Passez un délégué pour une méthode de rappel à BeginInvoke. La méthode est exécutée sur un thread ThreadPool lorsque l'appel asynchrone est terminé. La méthode de rappel appelle EndInvoke.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X