BeginInvoke上的内存泄漏

时间:2009-11-29 07:43:21

标签: c# delegates

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 个答案:

答案 0 :(得分:4)

虽然您的示例是正确的,但是使用不同的线程没有任何好处,因为您在主线程上调用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();
        }
    }
}

就内存泄漏而言,您可以查看此thread

P.S:List<T>类的实例成员不是线程安全的,因此当您从多个线程访问它们时应该小心。

答案 1 :(得分:2)

MSDN article on Begin/EndInvoke()

基本上,如果你不打电话给EndInvoke(),你就有可能泄漏某些东西。通常是某个内存中的内存或永远停滞的线程。

本文讨论了使用BeginInvoke()的四种常用方法,以及何时应为每个方法调用EndInvoke()

对于后代,我会在这里复制它们:

  • 做一些工作,然后调用EndInvoke来阻止,直到调用完成。

  • 使用System.IAsyncResult.AsyncWaitHandle属性获取WaitHandle,使用其WaitOne方法阻止执行,直到发出WaitHandle信号,然后调用EndInvoke。

  • 轮询BeginInvoke返回的IAsyncResult以确定异步调用何时完成,然后调用EndInvoke。

  • 将一个回调方法的委托传递给BeginInvoke。异步调用完成时,该方法在ThreadPool线程上执行。回调方法调用EndInvoke。

相关问题