为什么BackgroundWorker在代理上调用BeginInvoke时不需要调用EndInvoke?

时间:2015-02-20 23:00:04

标签: c# .net

post表示当您在委托上调用BeginInvoke方法时,始终需要调用EndInvoke方法。另一个post支持它并建议将班级BackgroundWorker作为替代。

我使用ILSpy反编译BackgroundWorker我发现实际上,EndInvoke 从未在此类中调用,即使它确实使用BeginInvoke代表。

这是否意味着BackgroundWorkder执行不当,或者调用EndInvoke不是必要的?

(丢失异常的问题无关紧要,因为调用的整个方法都包含在try-catch块中)

关于类似问题:有一个明确的理由说明BeginInvokeBackgroundWorker的实施中选择了ThreadPool.QueueUserWorkItem()而不是BackgroundWorker

修改:可以查看{{1}}的源代码here

1 个答案:

答案 0 :(得分:1)

我找了一会儿幕后男人。 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用户。但微软这样做,所以一定没问题。源代码中的注释会很好。