EndInvoke()是可选的,sort-of optional,还是绝对不是可选的?

时间:2009-02-10 15:10:40

标签: c# multithreading delegates

我已经阅读了关于每个BeginInvoke()是否必须与EndInvoke()匹配的矛盾意见。是否有任何与NOT调用EndInvoke()相关的泄漏或其他问题?

7 个答案:

答案 0 :(得分:53)

委托.EndInvoke记录为你要调用此(即必要的 - 否则会发生泄漏) - 来自msdn

  

重要提示

     

无论您使用哪种技术,   总是调用EndInvoke来完成你的   异步调用。

Control.EndInvoke可以忽略“即发即弃”方法 - 来自msdn

  

您可以调用EndInvoke来检索   从委托返回值,如果   必要的,但这不是必需的。

但是 - 如果您使用Delegate.BeginInvoke并且不想要结果,请考虑使用ThreadPool.QueueUserWorkItem代替 - 它会让生活变得更轻松,并避免IAsyncResult的痛苦等

答案 1 :(得分:18)

EndInvoke不是可选的。

更多信息here

答案 2 :(得分:9)

并且EndInvoke调用不是可选调用,它是合同的一部分。如果调用BeginInvoke,则必须调用EndInvoke。

为什么这是必要的经典例子。从BeginInvoke返回的IAsyncResult很可能已经分配了附加到它的资源。最常见的是WaitHandle。因为IAsyncResult没有实现IDisposable,所以必须选择另一个地方来释放资源。唯一可以这样做的地方是EndInvoke。

我在以下博客文章中简要讨论了这个问题。

http://blogs.msdn.com/jaredpar/archive/2008/01/07/isynchronizeinvoke-now.aspx

答案 3 :(得分:4)

EndInvoke不是可选的,因为如果在异步处理中出现错误,它就是抛出异常的地方。

无论如何都不应该有任何泄漏,因为如果IAsyncResult持有一些本机资源,它应该正确实现IDisposable并在GC调用终结器时处理这些资源。

答案 4 :(得分:3)

它不是可选的,因为调用BeginInvoke会使用WaitHandle,而WaitHandle又使用一个内核对象来维护对它有多少引用的计数。调用EndInvoke会优雅地处理在内核对象上递减该计数器的句柄,当该计数达到零时,内核对象管理器将销毁它。

答案 5 :(得分:2)

如果您不介意程序的内存增长非常大,那么它是唯一可选的。问题是GC保留了线程中的所有引用,因为您可能希望在某个时刻调用EndInvoke。我会选择Marc的答案,线程池会让你的生活更轻松。但是,您需要注意是否从线程中生成线程,因为它可以旋转的线程数量有限。

答案 6 :(得分:2)

此帖子上的每个回复都说EndInvoke()不是可选的。但是,我发现以下排名很高的评论是这个SO线程上接受的答案:

“请注意,Windows窗体团队已经保证您可以以'即发即忘'的方式使用Control.BeginInvoke - 即无需调用EndInvoke。通常情况下,异步调用不是这样:通常每个BeginXXX应该有一个相应的EndXXX调用,通常在回调中。“

What's the difference between Invoke() and BeginInvoke()