2009-08-13 45 views
8

我讀了Use AsyncCallback,有這樣的代碼片段:應該總是調用EndInvoke在AsyncCallback內委託嗎?

using System; 
using System.Threading; 
using System.Runtime.Remoting.Messaging; 
class MainClass 
{ 
    delegate int MyDelegate(string s); 

    static void Main(string[] args) 
    { 
    MyDelegate X = new MyDelegate(DoSomething); 
    AsyncCallback cb = new AsyncCallback(DoSomething2); 
    IAsyncResult ar = X.BeginInvoke("Hello", cb, null); 

    Console.WriteLine("Press any key to continue"); 
    Console.ReadLine(); 
    } 
    static int DoSomething(string s) 
    { 
    Console.WriteLine("doooooooooooooooo"); 
    return 0; 
    } 

    static void DoSomething2(IAsyncResult ar) 
    { 
    MyDelegate X = (MyDelegate)((AsyncResult)ar).AsyncDelegate; 
    X.EndInvoke(ar); 
    } 
} 

注意,在DoSomething2,這是一個AsyncCallback,委託明確由命令EndInvoke殺害。

這真的有必要嗎?由於AsyncCallback不會被調用,除非直到委託方法完成運行。

+1

BTW:相比於使用線程池時Delegate.BeginInvoke效率比較低,這裏的一些信息頁面:http://shevaspace.blogspot.com/2007/08/delegatebegininvoke-vs.html – STW 2009-08-13 04:30:33

+1

@Yoooder,這讓我感到驚訝,因爲BeginInvoke也使用ThreadPool。在這裏閱讀:http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx – tuinstoel 2009-08-13 04:44:21

+0

它也讓我感到驚訝,實際上有點震驚和失望我(這是我的首選異步工作模式),但似乎成爲事實。我們已經在使用ThreadPool的自定義實現中複製了模式,而不使用Remoting的東西 - 模式的所有好處,沒有任何開銷。 – STW 2009-08-13 05:06:34

回答

6

調用EndInvoke()非常重要。如果後臺方法生成異常,則調用EndInvoke()將引發該異常,從而允許主線程處理它。另外,如果後臺方法具有返回值,則主線程需要調用EndInvoke()來檢索該值。

如果你的後臺線程下屬於上述任何一種情況(生成異常或有返回值),你調用EndInvoke(),那麼後臺線程不會被釋放 - 本質導致資源泄漏。