2009-11-29 103 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。