2009-08-13 44 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(),那么后台线程不会被释放 - 本质导致资源泄漏。