【问题标题】:WCF service and IDisposable, do I clean up managed objects?WCF 服务和 IDisposable,我是否清理托管对象?
【发布时间】:2010-11-24 19:33:39
【问题描述】:

我已经实现了这样的 WCF 服务:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single, UseSynchronizationContext=false)]
public sealed class SynchronizationService : ISynchronizationService, IDisposable
{
   private MemoryStream objectStream;

   ...
}

ISyncrhonizationService 具有 [ServiceContract(SessionMode = SessionMode.Required)]。

如果客户端正确通信并最终调用具有 [IsTerminating=true] 的方法,那么我可以很好地处理 objectStream 变量。如果由于某种原因服务和客户端之间的通信中断,我想自己从服务端清理 objectStream 变量,这就是我要实现 IDisposable 接口的原因。但是查看 MSDN 文档 (http://msdn.microsoft.com/en-us/library/system.idisposable.aspx) 我对此有点怀疑,因为根据文档:

    // Dispose(bool disposing) executes in two distinct scenarios.
    // If disposing equals true, the method has been called directly
    // or indirectly by a user's code. Managed and unmanaged resources
    // can be disposed.
    // If disposing equals false, the method has been called by the
    // runtime from inside the finalizer and you should not reference
    // other objects. Only unmanaged resources can be disposed.

因为运行时会调用 Dispose 方法,然后 disposing = false。因此我不应该访问 objectStream,因为它是一个托管对象。在这种情况下,运行时提供的 SyncrhonizationService 终结器应该清理 objectStream 本身,我根本不需要实现 IDisposable。然而,一些论坛帖子表明,SyncrhonizationService 实例将被重用而不是处置/最终确定。

所以我的问题是:

1) 在异常/故障/超时/等期间,SyncrhonizationService 实例实际发生了什么?以后会被丢弃还是干脆重复使用?

2) 我是否需要实现 IDisposable 并在 Dispose() 方法中处理托管对象?

3) 是否有比 IDisposable 更好的替代方案,例如 channel_Faulted 事件?如果我确实在此类事件中处理了我的托管对象,我将如何以及在何处删除事件处理程序(我可以在事件处理程序中执行此操作,但如果发生另一种类型的异常/故障怎么办)?

【问题讨论】:

  • 请注意,IDisposable 没有 Dispose(bool) 重载。 MSDN 中引用的 cmets 记录了给出的代码示例,而不是指定 IDisposable 行为。终结器不会自动调用 Dispose - 您必须对其进行显式编码才能执行此操作,如代码示例中所示。如代码示例所示添加 Dispose(bool) 覆盖是执行此操作的标准模式。对于您的服务,您可以确信 WCF 将在 Session 结束时调用您的 Dispose() 方法,因此您不需要(也不应该拥有)终结器。
  • 感谢您的澄清,现在一切都说得通了 :)

标签: wcf


【解决方案1】:

如果您实现 IDisposable,您可以在 Dispose() 方法的实现中清理托管对象。

使用 PerSession InstanceContextMode,WCF 运行时将在会话结束时调用 SynchronisationService 对象上的 Dispose,无论是因为客户端关闭了他的代理;由于会话因不活动而超时(在客户端或服务器上);或通过通道故障。

服务实例不会被重用:新会话将获得 SynchronisationService 的新实例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-29
    • 2011-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多