Delegate.EndInvoke()真的有必要吗?

Ach*_*les 25 .net delegates begininvoke

我已经阅读了几个论坛,甚至还有一个或两个stackoverflow问题,说使用Delegate.BeginInvoke时需要Delegate.EndInvoke.我读过的很多关于使用BeginInvoke的文章都未提及使用EndInvoke.此外,我仅使用BeginInvoke部署了生产代码,并且似乎没有任何内存问题.我使用BeginInvoke的方式通常是线程,我不关心它们完成或处理多长时间.

Dan*_*Tao 45

从MSDN文章'异步调用同步方法':

无论使用哪种技术,始终调用EndInvoke来完成异步调用.

现在,有理论,然后有实践.您已经发现,像您之前的许多其他开发人员一样,您通常可以忽略此记录的要求.它可能是一个实现细节,是否EndInvoke实际上做了一些绝对必要的事情来防止你的应用程序崩溃,泄漏内存等.但事情是这样的:如果它是一个记录的要求,你真的应该这样做.这不仅仅与理论有关; 它是关于在发生变化时保护自己.

通过记录这一要求,这种异步调用机制的设计者基本上可以自由地改变方式BeginInvoke并在线下EndInvoke工作,这样,如果有足够的理由(例如,性能增强),EndInvoke可能会突然变得更加必要.假设如果你忘记它会突然导致死锁.他们已经通过说总是打电话来EndInvoke掩盖自己; 如果你的应用因为你没有遵循这个要求而停止工作,那么你就有责任.

我不是说这必然是一种可能的情况.我的观点很简单,你应该- 或者至少我不会 - "这真的有必要吗?" 用的心态.如果我能逃脱离开它,那么我会,因为它记录在案,你应该这样做.


Dav*_*ave 13

如果你计划从你的线程中抛出异常并期望正确捕获它们,这是绝对必要的.如果您不调用EndInvoke,则抛出异常的线程将消失,您将不会知道任何有关它的信息.

要支持EndInvoke,请提供AsyncCallback,并在该回调方法中,确保使用try/catch块将您的调用包装到EndInvoke.

虽然如果你不关心线程中发生的事情,你可以逃避不做,我认为这是一个非常好的习惯,只需要调用EndInvoke.你永远不会知道,一个初级开发人员有一天可以进入并改变你的线程中的代码,然后抛出异常.然后部署更新的应用程序,服务调用开始进入.


Jah*_*ine 9

我听说过可能出现的内存泄漏问题.

通过关键字搜索,我找到了一个很好的讨论.

Does not calling EndInvoke *really* cause a memory leak ?

It can but it won't necessarily. Technically there is no such thing as a memory leak in .NET. Eventually the memory will be reclaimed by the GC. The problem is that it might be around a long time. The reason that you should call EndInvoke is because the results of the invocation (even if there is no return value) must be cached by .NET until EndInvoke is called. For example if the invoked code throws an exception then the exception is cached in the invocation data. Until you call EndInvoke it remains in memory. After you call EndInvoke the memory can be released.

这是参考,

另一个参考