每个BeginInvoke都必须跟随一个EndInvoke吗?

26

MS文档中的此页面涵盖了Windows Forms应用程序中的异步操作,其中指出:

如果需要,您可以调用EndInvoke从委托中检索返回值,但这不是必需的。(已加重)

涵盖异步委托一般情况的此页面则说明了不同的内容:

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

这两者似乎存在直接冲突。

哪一个是真实的?有人能解释一下吗?

另请参阅Phil Haack的帖子

相关:EndInvoke是可选的、有点可选的还是肯定不可选的?

3个回答

25

除非接口文档显式说明,否则在每次调用BeginInvoke后必须调用EndInvoke。主要原因是EndInvoke是所有者可以安全释放为BeginInvoke调用分配的某些资源(例如WaitHandle)的唯一时间。

但也有例外情况。像Control.BeginInvoke这样的API不需要EndInvoke,但文档中明确说明了。


14

两种说法都是真的 - 它们是不同的调用。

一般而言,您应该始终调用 EndInvoke 来确保释放异步调用获取的任何资源。

然而,Windows Forms 团队已经保证您在 Control.Invoke 中不需要这样做。尽管如此,对于 ISynchronizeInvoke 的其他实现,您可能仍需要这样做。


我同意你的大部分回答,除了关于它们是“不同调用”的评论。它们似乎根本不是不同的调用。它们都在讨论异步委托上的EndInvoke,难道不是吗?只是控制委托上的EndInvoke是一个特殊情况。 - Cheeso
3
不 - Control.BeginInvoke并不是对委托的调用。它需要一个委托。 - Jon Skeet

1

我以前使用过委托的“发射并忘记”方法,其中结果“如果可用则有用,但不是必需的”。只要记住,该方法没有完成保证。特别是,这里是我使用它的一个地方:

  • 启动一个委托来检查应用程序更新
  • 委托开始一个带有超时的Web请求
  • 如果出现错误/超时,或者应用程序已经是最新版本,则该方法仅返回
  • 如果应用程序已过期,则会放置一个非焦点窗口的系统托盘消息(除非更新可用,否则没有系统托盘图标)

无论哪种方式,应用程序都可以继续运行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接