每个BeginInvoke必须跟一个EndInvoke吗?

时间:2009-08-13 20:07:20

标签: .net multithreading begininvoke

This page in the MS documentation,涵盖Windows窗体应用程序中的异步,声明:

  

如果需要,可以调用EndInvoke从委托中检索返回值,但不需要。(强调添加)

This page covering the general case of asynchronous delegates,陈述不同之处:

  

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

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

哪个是真的?有人可以解释一下吗?

另见a post by Phil Haack

  

相关:Is EndInvoke optional, sort-of optional, definitely not optional?

3 个答案:

答案 0 :(得分:22)

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

但这条规则有例外。诸如Control.BeginInvoke之类的API不需要EndInvoke,但它在文档中是明确的。

答案 1 :(得分:13)

两者都是真的 - 他们是不同的电话。

通常,您应该始终调用EndInvoke以确保释放异步调用获取的任何资源。

但是,Windows窗体团队保证您不需要为Control.Invoke执行此操作。您可能需要为ISynchronizeInvoke的其他实现执行此操作。

答案 2 :(得分:1)

我在代表之前使用了“即发即弃”方法,结果“如果可用,但不是必需的”是有用的。请记住,您没有使用该方法的完成保证。特别是,这是我使用它的一个地方:

  • 启动代理以检查应用程序更新
  • 委托开始超时的网络请求
  • 如果发生错误/超时,或者应用程序是最新的,则该方法只返回
  • 如果应用程序已过期,我会发出一条非焦点窃取的系统托管消息(除非有更新,否则不会出现系统托盘图标)

无论哪种方式,应用程序都会不间断地继续。