我是否需要关闭和/或处置通过OperationContext.Current.GetCallbackChannel 获取的回调通道?

发布于 2024-12-16 18:47:38 字数 117 浏览 1 评论 0原文

我正在使用 OperationContext.Current.GetCallbackChannel 获取调用 WCF 服务操作的客户端的通道。

我是否需要担心关闭/处置这些回调通道,或者这是由框架处理的?

I'm using OperationContext.Current.GetCallbackChannel to get a channel to the client that called a WCF service operation.

Do I need to worry about closing / disposing these callback channels or is this taken care of by the framework?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

青衫负雪 2024-12-23 18:47:38

嗯,我刚刚自己尝试了一下,结果发现如果你 Close &处置回调通道(在转换为 IClientChannel 后)整个服务通道变得无用,并且在调用时抛出 ProtocolException 并指出:

“由于服务器启动的关闭,输出会话已自动关闭,因此该通道无法再用于发送消息通过将 DispatchRuntime.AutomaticInputSessionShutdown 设置为 false 来禁用自动关闭,或者考虑修改远程服务器的关闭协议。”

我认为这是尝试关闭和关闭的不受欢迎的后果或副作用。处置回调通道,这意味着不应该这样做。

Well, I just tried it myself and it turns out that if you Close & Dispose the callback channel (after casting to IClientChannel) the entire Service channel becomes useless and when called throws a ProtocolException saying:

"This channel can no longer be used to send messages as the output session was auto-closed due to a server-initiated shutdown. Either disable auto-close by setting the DispatchRuntime.AutomaticInputSessionShutdown to false, or consider modifying the shutdown protocol with the remote server."

I assume that this is an unwelcome consequence or side effect of attempting to close & dispose the callback channel, meaning that this should not be done.

心的憧憬 2024-12-23 18:47:38

我认为你应该这样做。

回调机制不提供任何类似于管理
服务和回调端点之间的连接。由开发商决定
提出一些应用程序级协议或一致的模式来管理
连接的生命周期。仅当客户端通道仍然打开时,服务才能回调客户端,这通常是通过不关闭代理来实现的。保持代理打开还将防止回调对象被垃圾收集。如果服务在回调端点上维护引用,并且客户端代理已关闭或客户端应用程序本身已消失,则当服务调用回调时,它将从服务通道获取 ObjectDisposeException。因此,客户端最好在不再希望接收回调或客户端应用程序关闭时通知服务。为此,您可以向服务协定添加显式 Disconnect() 方法。由于每个方法调用都带有回调引用,因此在 Disconnect() 方法中,服务可以从其内部存储中删除回调引用。

这是一个例子:

class MyService : IServiceContract
{
   static List<IServiceContractCallback> m_Callbacks = new List<IServiceContractCallback>();
public void Connect()
{
    IServiceContractCallbackcallback = OperationContext.Current.GetCallbackChannel<IServiceContractCallback>();
    if(m_Callbacks.Contains(callback) == false)
    {
       m_Callbacks.Add(callback);
    }
}
public void Disconnect()
{
    IServiceContractCallback callback = OperationContext.Current.GetCallbackChannel<IServiceContractCallback>();
    if(m_Callbacks.Contains(callback))
    {
        m_Callbacks.Remove(callback);
    }
    else
    {
        throw new InvalidOperationException("Cannot find callback");
    }
}

通过这种方式,客户端可以通知服务不再需要回调。它能回答你的问题吗?

In my opinion you should.

The callback mechanism supplies nothing like a higher-level protocol for managing the
connection between the service and the callback endpoint. It is up to the developer to
come up with some application-level protocol or a consistent pattern for managing the
lifecycle of the connection. The service can only call back to the client if the client-side channel is still open, which is typically achieved by not closing the proxy. Keeping the proxy open will also prevent the callback object from being garbage-collected. If the service maintains a reference on a callback endpoint and the client-side proxy is closed or the client application itself is gone, when the service invokes the callback it will get an ObjectDisposedException from the service channel. It is therefore preferable for the client to inform the service when it no longer wishes to receive callbacks or when the client application is shutting down. To that end, you can add an explicit Disconnect() method to the service contract. Since every method call carries the callback reference with it, in the Disconnect() method the service can remove the callback reference from its internal store.

here is an exemple :

class MyService : IServiceContract
{
   static List<IServiceContractCallback> m_Callbacks = new List<IServiceContractCallback>();
public void Connect()
{
    IServiceContractCallbackcallback = OperationContext.Current.GetCallbackChannel<IServiceContractCallback>();
    if(m_Callbacks.Contains(callback) == false)
    {
       m_Callbacks.Add(callback);
    }
}
public void Disconnect()
{
    IServiceContractCallback callback = OperationContext.Current.GetCallbackChannel<IServiceContractCallback>();
    if(m_Callbacks.Contains(callback))
    {
        m_Callbacks.Remove(callback);
    }
    else
    {
        throw new InvalidOperationException("Cannot find callback");
    }
}

In such a way a client can inform the service that the callback is no longer needed. Does it answer your question ?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文