在这个问题上已有很多讨论,每个人似乎都同意您应该始终调用Delegate.EndInvoke以防止内存泄漏(即使Jon Skeet也是这么说的!)。
我一直遵循这个指导方针而没有质疑过,但最近我实现了自己的AsyncResult类,并发现唯一可能泄漏的资源是AsyncWaitHandle。
(实际上它并不会真正泄漏,因为WaitHandle使用的本机资源封装在一个具有Finalizer的SafeHandle中,它会对垃圾收集器的finalize队列产生压力。即便如此,一个良好的AsyncResult实现只会按需初始化AsyncWaitHandle...)
了解是否存在泄漏的最好方法就是尝试它:
Action a = delegate { };
while (true)
a.BeginInvoke(null, null);
我运行了这个程序一段时间,内存使用量保持在9-20 MB之间。
现在我们来比较一下当调用Delegate.EndInvoke时:
Action a = delegate { };
while (true)
a.BeginInvoke(ar => a.EndInvoke(ar), null);
通过这个测试,内存使用量在9-30MG之间波动,很奇怪吧?(可能是因为当有AsyncCallback时执行时间较长,因此线程池中会有更多排队的委托)
你认为... "神话被打破"了吗?
P.S. ThreadPool.QueueUserWorkItem比Delegate.BeginInvoke效率高一百倍,最好用于fire & forget调用。