【问题标题】:When using WCF callbacks how do clients know if the server has been interrupted使用 WCF 回调时,客户端如何知道服务器是否已中断
【发布时间】:2014-07-11 14:48:12
【问题描述】:

如果我创建一个提供回调的 WCF 服务,并且我有多个注册以接收事件的客户端,那么这些客户端如何知道服务是否中断或关闭?目前,他们只是等待一个永远不会触发的事件。

我想也许我可以实现某种轮询(这是我试图摆脱的)。但即使是民意调查似乎也是一个糟糕的解决方案。例如,如果我每 30 秒轮询一次,但服务或应用程序池在下一次检查之前重新启动,那么客户端会认为一切都很好,尽管服务器已经失去了对它们的引用。

【问题讨论】:

  • 您是否考虑过通过代理类使用超时机制?可能是内置的。
  • 恐怕我不完全确定你的意思?

标签: c# wcf service callback


【解决方案1】:

您可以利用IClientChannel 上的各种事件来监控连接发生的情况。对于您的情况,Faulted 事件似乎是最合适的。但还有其他一些您可能会觉得有用的活动。

    _proxy.InnerChannel.Opening += OnChannelOpening;
    _proxy.InnerChannel.Opened += OnChannelOpened;
    _proxy.InnerChannel.Faulted += OnChannelFaulted;
    _proxy.InnerChannel.UnknownMessageReceived += OnChannelUnknownMessageReceived;
    _proxy.InnerChannel.Closing += OnChannelClosing;
    _proxy.InnerChannel.Closed += OnChannelClosed;

【讨论】:

  • 你是对的,这是我需要订阅的 InnerChannel.Faulted。不过,我现在也将为许多其他事件添加处理程序。非常感谢!
【解决方案2】:

看看我写的这个存储库来回答另一个问题:https://github.com/Aelphaeis/MyWcfDuplexPipeExample/tree/MultiClient

在这个存储库中有一个双工连接和两个客户端。

如果在您尝试调用客户端回调函数时客户端断开连接并且服务尝试访问客户端,您将捕获 CommunicationObjectAbortedException。

如果服务断开连接并且客户端尝试调用服务,您应该尝试捕获 EndPointNotFoundException。

public class MyServiceClient: IMyService, IDisposable
{
    DuplexChannelFactory<IMyService> myServiceFactory { get; set; }

    public MyServiceClient(IMyServiceCallback Callback)
    {
        InstanceContext site = new InstanceContext(Callback);
        NetNamedPipeBinding binding = new NetNamedPipeBinding();
        EndpointAddress endpointAddress = new EndpointAddress(Constants.myPipeService + @"/" + Constants.myPipeServiceName);

        myServiceFactory = new DuplexChannelFactory<IMyService>(site, binding, endpointAddress);
        Init();
    }
    public void Init()
    {
        myServiceFactory.CreateChannel().Init();//EndPointNotFoundException Thrown here
    }

    public void DoWork()
    {
        myServiceFactory.CreateChannel().DoWork();//EndPointNotFoundException Thrown here
    }

    public void Dispose()
    {
        myServiceFactory.Close();
    }
}

服务

public class MyServiceServer : IDisposable
{
    public Boolean IsDisposed { get; private set; }
    ServiceHost host { get; set; }
    MyService service;
    public void Open()
    {
        if (host != null)
            Dispose();

        IsDisposed = false;
        service = new MyService();
        host = new ServiceHost(service, new Uri(Constants.myPipeService));
        host.AddServiceEndpoint(typeof(IMyService), new NetNamedPipeBinding(), Constants.myPipeServiceName);

        host.BeginOpen(OnOpen, host);
    }

    public void Msg(int ClientId)
    {
        foreach (var cb in service.Callbacks)
            if (cb.GetClientId() == ClientId) // CommunicationObjectAbortedException here
                cb.RecieveMessage("We have called you choosen one");
    }

    public void Close()
    {
        host.BeginClose(OnClose, host);
    }

    public void Dispose()
    {
        ((IDisposable)host).Dispose();
        IsDisposed = true;
        host = null;
    }

    void OnOpen(IAsyncResult ar)
    {
        ServiceHost service = (ServiceHost)ar.AsyncState;
        service.EndOpen(ar);
    }
    void OnClose(IAsyncResult ar)
    {
        ServiceHost service = (ServiceHost)ar.AsyncState;
        service.EndClose(ar);
        Dispose();
    }
}

【讨论】:

  • 这是一个很好的例子!它涵盖了很多我还没想过解决的问题。我将研究它并运行几次。这将极大地帮助我生产质量更好的东西。非常感谢!
  • 一个不错的答案。稍微偏离主题的是您没有正确意识到IDisposable。请参考MSDN - Implementing a Dispose Method
  • @MickyDuncan 谢谢你,我不知道。我会仔细阅读的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-22
  • 2019-02-23
  • 1970-01-01
  • 1970-01-01
  • 2016-05-28
相关资源
最近更新 更多