3 Stimmen

Speicherleck bei BeginInvoke

1) Ich habe gehört, dass es zu einem Speicherleck kommen kann, wenn wir EndInvoke() nicht aufrufen. Können Sie demonstrieren, wie es zu einem Speicherleck kommen kann?

2) Wenn ich EndInvoke() aufrufen soll, soll ich den Code wie folgt verwenden?

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 Punkte 990883

Während Ihr Beispiel korrekt ist, gibt es keinen Vorteil durch die Verwendung eines anderen Threads, weil Sie die EndInvoke auf dem Hauptthread, der so lange blockiert, bis der Vorgang abgeschlossen ist und er keine andere Arbeit ausführen kann. Es wäre gleichwertig gewesen, wenn Sie Invoke auf den Delegierten oder direkt die FinalResult Methode selbst. Normalerweise EndInvoke wird in dem Callback aufgerufen, der von der BeginInvoke Methode:

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

Was das Speicherleck betrifft, so können Sie einen Blick auf Folgendes werfen Gewinde .

P.S.: Die Instanzmitglieder der Liste<T> Klasse sind nicht thread-sicher, daher sollten Sie vorsichtig sein, wenn Sie von mehreren Threads aus auf sie zugreifen.

2voto

Kevin Montrose Punkte 21631

MSDN-Artikel über Begin/EndInvoke()

Im Grunde genommen, wenn Sie nicht EndInvoke() laufen Sie Gefahr, undicht zu werden etwas . In der Regel entweder Speicher oder ein für immer festgehaltener Thread in einem Pool irgendwo.

In dem Artikel werden vier gängige Möglichkeiten der Verwendung von BeginInvoke() und wann Sie anrufen sollten EndInvoke() für jeden.

Der Nachwelt zuliebe werde ich sie hier wiedergeben:

  • Erledigen Sie einige Aufgaben und rufen Sie dann EndInvoke auf, um zu blockieren, bis der Aufruf abgeschlossen ist.

  • Beziehen Sie einen WaitHandle mit der Eigenschaft System.IAsyncResult.AsyncWaitHandle, verwenden Sie dessen WaitOne-Methode, um die Ausführung zu blockieren, bis der WaitHandle signalisiert wird, und rufen Sie dann EndInvoke auf.

  • Das von BeginInvoke zurückgegebene IAsyncResult abfragen, um festzustellen, wann der asynchrone Aufruf abgeschlossen ist, und dann EndInvoke aufrufen.

  • Übergeben Sie einen Delegaten für eine Callback-Methode an BeginInvoke. Die Methode wird auf einem ThreadPool-Thread ausgeführt, wenn der asynchrone Aufruf abgeschlossen ist. Die Callback-Methode ruft EndInvoke auf.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X