Do I need to Close and/or Dispose callback channels acquired through OperationContext.Current.GetCallbackChannel?

后端 未结 2 1914
一整个雨季
一整个雨季 2021-02-13 10:21

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

相关标签:
2条回答
  • 2021-02-13 10:39

    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 ?

    0 讨论(0)
  • 2021-02-13 10:40

    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.

    0 讨论(0)
提交回复
热议问题