这篇文章说,当您在委托上调用BeginInvoke
方法时,总是需要调用EndInvoke
方法。另一篇文章对此进行了支持,并建议使用BackgroundWorker
类作为替代。
我使用ILSpy来反编译BackgroundWorker
,我发现实际上,EndInvoke
在这个类中从未被调用过,尽管它确实在委托上使用了BeginInvoke
。
这是否意味着BackgroundWorkder
实现不好,或者调用EndInvoke
根本没有必要?
(异常丢失的问题无关紧要,因为被调用的整个方法都包含在try-catch块中)
在类似的问题上:为什么在BackgroundWorker
的实现中选择BeginInvoke
而不是ThreadPool.QueueUserWorkItem()
有明确的原因吗?
编辑:BackgroundWorker
的源代码可以在这里查看。
我在窗帘后面找了一会儿那个人。CLR拥有SynchronizationContext类的秘密知识,因此从技术上讲,它可能会参与其中。什么也没发现。
在我检查了我应该做的事情之前,请实际验证EndInvoke()是必需的声明:
using System;
class Program {
static void Main(string[] args) {
Action d = null;
d = new Action(() => {
d.BeginInvoke(null, null);
});
d();
Console.ReadLine();
}
}
像黑帮杀手一样奔跑,消耗大量手柄。但它不会爆炸,它们永远不会超过2000,内存使用情况完全稳定。
因此,也许调整调用委托的EndInvoke()的声明是合适的。如果你事先知道委托目标不会做任何异常的事情,比如调用另一个AppDomain、运行本机代码或激活远程代码,那么你可以不调用EndInvoke()。BackgroundWorker可以提供的保证。作为一个纯粹的SO用户,我永远无法坚持这种说法。但微软做到了,所以肯定没问题。在源代码中添加一条注释会很好。