【问题标题】:Change in one WCF service should update the same change in other instances of the same WCF services一个 WCF 服务中的更改应更新相同 WCF 服务的其他实例中的相同更改
【发布时间】:2018-02-28 08:53:52
【问题描述】:

我托管了同一个 WCF 服务的多个实例。如果其中一个服务实例发生变化,那么它也应该在其他服务中得到通知/更新。我实现了这样的解决方案,即 WCF 服务使用 DuplexChannelFactory 充当客户端和服务器。但是为了做到这一点,服务需要注册它的对等点,我在服务的构造函数中这样做。这会导致死锁,因为它永远不会相互初始化。这种逻辑在 WCF 服务中是如何实现的?

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Timers;
using WcfServiceLibrary.PeerServiceReference;

namespace WcfServiceLibrary
{
    public interface IHeartbeat
    {
        bool Pulse();
        void Ping();
    }

    [ServiceContract(CallbackContract = typeof(INotifications))]
    public interface ISubscription : IHeartbeat, INotifications
    {
        [OperationContract(IsOneWay = true)]
        void Subscribe(string ServiceName);
        [OperationContract(IsOneWay = true)]
        void Unsubscribe(string ServiceName);
    }

    [ServiceContract]
    public interface INotifications
    {
        [OperationContract(IsOneWay = true)]
        void UpdateData(int newValue);
    }

    [ServiceContract]
    public interface IUserService
    {
        [OperationContract(IsOneWay = true)]
        void MethodThatWillChangeData(int value);
    }
    public class ObservableService : IUserService, ISubscription
    {
        private static Dictionary<string, ISubscription> _Peers = new Dictionary<string, ISubscription>();
        private int ClientAge;
        private string ServiceName { get; }
        private Timer _timer = new Timer() { Interval = 5000 };
        private IWriter _writer;
        public ObservableService() : this(new ConsoleWriter())
        {

        }
        public ObservableService(IWriter writer)
        {
            _writer = writer;
            _writer.WriteLine("Initiating construction...");
            ServiceName = ConfigurationManager.AppSettings["ServiceName"];
            _timer.Elapsed += Timer_Elapsed;
            _timer.Start();
            var PeerServersList = ConfigurationManager.AppSettings["PeerServers"].Split(';');
            var callback = new InstanceContext(this);
            foreach (var peer in PeerServersList)
            {
                try
                {
                    var dualBinding = new WSDualHttpBinding();
                    var address = new EndpointAddress(peer);
                    var PeerServiceFactory = new DuplexChannelFactory<ISubscription>(callback, dualBinding);
                    var PeerService = PeerServiceFactory.CreateChannel(address);
                    PeerService.Subscribe(ServiceName);
                }
                catch (Exception ex)
                {
                    //TODO handle the exception
                }
            }
        }

        private void Timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            _writer.WriteLine("Pinging the data");
            this.Ping();
        }

        public void MethodThatWillChangeData(int newValue)
        {
            _writer.WriteLine($"MethodThatWillChangeData with {newValue}");
            var PreviousClientAge = ClientAge;
            ClientAge = newValue;
            foreach (var peer in _Peers)
            {
                _writer.WriteLine($"Calling update on the client {peer.Key}");
                peer.Value.UpdateData(newValue);
            }
        }

        public void Ping()
        {
            var test = _Peers.Keys.ToList();
            for (int i = _Peers.Count - 1; i >= 0; i--)
            {
                try
                {
                    _writer.WriteLine($"Checking the pulse of {test[i]}");
                    _Peers[test[i]].Pulse();
                }
                catch (Exception)
                {
                    _Peers.Remove(test[i]);
                }
            }
        }

        public bool Pulse()
        {
            _writer.WriteLine($"Pulse requested...");
            return true;
        }

        public void UpdateData(int newValue)
        {
            _writer.WriteLine($"Updating the data to {newValue} from {ClientAge}");
            ClientAge = newValue;
        }

        public void Unsubscribe(string ServiceName)
        {
            if (_Peers.Keys.Contains(ServiceName))
            {
                _Peers.Remove(ServiceName);
            }
        }

        public void Subscribe(string ServiceName)
        {
            if (!_Peers.Keys.Contains(ServiceName))
            {
                _writer.WriteLine($"Registering {ServiceName}...");
                _Peers.Add(ServiceName, OperationContext.Current.GetCallbackChannel<ISubscription>());
            }
        }
    }
}

【问题讨论】:

    标签: c# wcf


    【解决方案1】:

    我将有一个单独的 WCF 服务来管理您尝试在服务之间保持同步的任何数据,并让每个服务与之通信。

    或者,您将数据保存在数据库中,这样任何更改都会自动反映在服务中。

    【讨论】:

      猜你喜欢
      • 2020-05-18
      • 2011-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-04
      相关资源
      最近更新 更多