为什么BackgroundWorker在委托上调用BeginInvoke时不需要调用EndInvoke



这篇文章说,当您在委托上调用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用户,我永远无法坚持这种说法。但微软做到了,所以肯定没问题。在源代码中添加一条注释会很好。

最新更新