基于事件的异步模式可用于公开类的异步行为。 通过引入此模式,.NET 定义了两种用于公开异步行为的模式:基于 System.IAsyncResult 接口的异步模式和基于事件的模式。 本文介绍何时适合实现这两种模式。
有关使用IAsyncResult接口进行异步编程的详细信息,请参阅异步编程模型(APM)。
一般原则
通常,应尽可能使用基于事件的异步模式公开异步功能。 但是,存在一些基于事件的模式无法满足的要求。 在这些情况下,除了基于事件的模式外,可能需要实现 IAsyncResult 模式。
注释
通常情况下, 很少有 IAsyncResult 模式的实现不伴随事件驱动模式的实现。
准则
以下列表描述了何时应实现基于事件的异步模式的准则:
使用事件驱动模式作为默认 API 来呈现类的异步行为。
当类主要用于客户端应用程序(例如 Windows 窗体)时,请勿公开 IAsyncResult 模式。
只有在满足要求时才公开 IAsyncResult 模式。 例如,与现有 API 的兼容性可能需要公开 IAsyncResult 模式。
请勿在不公开基于事件的模式的情况下公开 IAsyncResult 模式。
如果必须公开模式 IAsyncResult ,请将其作为高级选项进行公开。 例如,如果生成代理对象,则默认生成基于事件的模式,并具有生成 IAsyncResult 模式的选项。
在你的 IAsyncResult 模式实现上构建基于事件的模式实现。
避免在同一类上公开基于事件的模式和 IAsyncResult 模式。 请对“高级”类公开基于事件的模式,并对“低级”类公开 IAsyncResult 模式。 例如,将组件上的 WebClient 基于事件的模式与 IAsyncResult 类上的 HttpRequest 模式进行比较。
当兼容性需要该模式时,公开同一类上的基于事件的模式和 IAsyncResult 模式。 例如,如果已发布使用模式的 IAsyncResult API,则需要保留 IAsyncResult 模式以实现向后兼容性。
如果生成的对象模型复杂性超过分离实现的好处,则公开同一类上的基于事件的模式和 IAsyncResult 模式。 最好在单个类上公开这两种模式,而不是避免公开基于事件的模式。
如果必须对一个类公开基于事件的模式和 IAsyncResult 模式,请将 EditorBrowsableAttribute 设置为 Advanced,以将 IAsyncResult 模式实现标记为高级功能。 这表示在设计环境中(如 Visual Studio IntelliSense),不显示 IAsyncResult 属性和方法。 这些属性和方法仍然完全可用,但通过 IntelliSense 工作的开发人员对 API 具有更清晰的视图。
除了基于事件的模式外还公开 IAsyncResult 模式的条件
虽然基于事件的异步模式在前面提到的方案中有很多好处,但它确实有一些缺点,如果性能是最重要的要求,应该注意这一点。
有三个场景是基于事件的模式未能像 IAsyncResult 模式那样有效地解决:
对 IAsyncResult 阻止等待操作
对多个 IAsyncResult 对象阻止等待操作
对 IAsyncResult 轮询完成状态
可以使用基于事件的模式来解决这些方案,但这样做比使用 IAsyncResult 模式更繁琐。
开发人员经常将 IAsyncResult 模式用于通常具有非常高的性能要求的服务。 例如,轮询完成状态就是一种高性能服务器技术。
此外,基于事件的模式比 IAsyncResult 模式效率低,因为它会创建更多对象,特别是 EventArgs因为它跨线程同步。
如果决定使用 IAsyncResult 模式,以下是一些建议供你参考:
仅当你特别需要支持IAsyncResult或WaitHandle对象时公开IAsyncResult模式。
仅在有使用 IAsyncResult 模式的现有 API 时,才公开 IAsyncResult 模式。
如果已有基于模式的 IAsyncResult API,请考虑在下一版本中公开基于事件的模式。
仅当您验证具有高性能要求且基于事件的模式无法满足时,而可以通过IAsyncResult模式来满足时,才公开IAsyncResult模式。