Утечка памяти при BeginInvoke - PullRequest
3 голосов
/ 29 ноября 2009

1) Я слышал, что когда мы не будем вызывать EndInvoke (), это может привести к утечке памяти? Вы можете продемонстрировать это, как это может привести к утечке памяти?

2) Когда я предполагаю вызвать EndInvoke (), я должен использовать код, подобный следующему?

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

    }
}

Ответы [ 2 ]

4 голосов
/ 29 ноября 2009

Хотя ваш пример верен, использование другого потока бесполезно, потому что вы вызываете EndInvoke в основном потоке, который блокируется до завершения операции и не может выполнять другую работу. Это было бы эквивалентно, если бы вы вызвали Invoke для делегата или непосредственно сам метод FinalResult. Обычно EndInvoke вызывается в обратном вызове, предоставляемом методом BeginInvoke:

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

Что касается утечки памяти, вы можете взглянуть на этот поток .

P.S: члены экземпляра класса List не являются поточно-ориентированными, поэтому следует соблюдать осторожность при доступе к ним из нескольких потоков.

2 голосов
/ 29 ноября 2009

Статья MSDN о Begin / EndInvoke ()

Обычно, если вы не позвоните EndInvoke(), вы рискуете протечь что-то . Обычно это либо память, либо вечно застопорившийся поток в пуле.

В статье рассматриваются четыре распространенных способа использования BeginInvoke() и когда вам следует звонить EndInvoke() для каждого.

Для потомков я воспроизведу их здесь:

  • Сделайте некоторую работу, а затем вызовите EndInvoke для блокировки до завершения вызова.

  • Получите WaitHandle с помощью свойства System.IAsyncResult.AsyncWaitHandle, используйте его метод WaitOne, чтобы заблокировать выполнение, пока не будет получен сигнал WaitHandle, а затем вызовите EndInvoke.

  • Опрос IAsyncResult, возвращенного BeginInvoke, чтобы определить, когда завершился асинхронный вызов, а затем вызов EndInvoke.

  • Передать делегат для метода обратного вызова в BeginInvoke. Метод выполняется в потоке ThreadPool после завершения асинхронного вызова. Метод обратного вызова вызывает EndInvoke.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...