2009-11-29 104 views
3

1)我听说当我们不会调用EndInvoke()时,它可能导致内存泄漏?你能证明它怎么会导致内存泄漏?BeginInvoke上的内存泄漏

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

    } 
} 

回答

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>类的实例成员不是线程安全的,因此您在从多个线程访问它们时应该小心。

2

MSDN article on Begin/EndInvoke()

基本上,如果你不叫EndInvoke()运行泄漏东西的风险。一般来说,无论是内存,还是永远停滞在某个池中的线程。

本文讨论了使用BeginInvoke()的四种常用方法,并且您应该每次调用EndInvoke()

对于后人,我将在这里重现出来:

  • 做一些工作,然后调用EndInvoke封锁,直到调用完成。

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

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

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