0

I use WCF Duplex to send/receive messages among users who subscribed in WCF in server. The WCF has three methods: Join (to subscribe), Leave (to unsubscribe) and SendAlert (to send message from a user to other users). The following is the server side code (AlertService in WCF duplex in server):

using System;
using System.Collections.Generic;
using System.ServiceModel;

namespace RahatWCF
{
    [ServiceContract(Name = "AlertService",
                     Namespace = "RahatWCF",
                     SessionMode = SessionMode.Required,
                     CallbackContract = typeof(IAlertCallback))]
    public interface IAlert
    {
        [OperationContract]
        int JoinTheConversation(int userId);

        [OperationContract(IsOneWay = true)]
        void SendAlert(int senderUserId, List<int> recieversUserId, string caption, string messageText);

        [OperationContract]
        int LeaveTheConversation(int userId);
    }

    public interface IAlertCallback
    {
        [OperationContract(IsOneWay = true)]
        void NotifyUserOfMessage(int senderUserId, List<int> recieversUserId, string caption, String messageText);
    }

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.PerCall)]
    public class AlertService : IAlert
    {
        private static List<IAlertCallback> _callbackList = new List<IAlertCallback>();

        public AlertService() { }

        public int JoinTheConversation(int userId)
        {
            IAlertCallback registeredUser = OperationContext.Current.GetCallbackChannel<IAlertCallback>();

            if (!_callbackList.Contains(registeredUser))
                _callbackList.Add(registeredUser);

            return _callbackList.Count;
        }

        public int LeaveTheConversation(int userId)
        {
            IAlertCallback registeredUser = OperationContext.Current.GetCallbackChannel<IAlertCallback>();

            if (_callbackList.Contains(registeredUser))
                _callbackList.Remove(registeredUser);

            return _callbackList.Count;
        }

        public void SendAlert(int senderUserId, List<int> recieversUserId, string caption, string messageText)
        {
            _callbackList.ForEach(
                delegate (IAlertCallback callback)
                {
                    callback.NotifyUserOfMessage(senderUserId, recieversUserId, caption, messageText);
                });
        }
    }
}

The above code is WCF Duplex that I implemented in server side. My WCF client application joins this WCF when the user logins into the app; And the client app leaves the WCF when the user logouts from the app. The problem is that if user suddenly terminates the app and not logout from client app then he/she cannot send message to other users later. I checked the issue and find out that when a user logins (joins) and does not logout (leave) then in server two channels are created for user and SendAlert does not work anymore in this situations. How can I solve this problem?

Mohsen
  • 971
  • 2
  • 11
  • 29

1 Answers1

0

Timeout is the key setting for duplex channels (if there are no messages sent or received). Keep them short and your channel will fault. If you send a response from the server you can react on faulted client channel and remove it from known channels. If client faults than it needs to re-join the server; which in that case you could remove other callbacks from your service.

Petar Vučetin
  • 3,555
  • 2
  • 22
  • 31
  • I increased 'receiveTimeout' and 'inactivityTimeout', but sometimes (that I don't know why) I get the error says 'The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it has been Aborted.' How can I solve this error? – Mohsen May 24 '16 at 06:14
  • You can take a look at [re-connect logic](http://stackoverflow.com/questions/14547034/wcf-channelfactory-and-channels-caching-reusing-closing-and-recovery/22124269#22124269) but the only thing you can do is re-create channel. – Petar Vučetin May 24 '16 at 14:22
  • Thank you. I will check and let you know. – Mohsen May 28 '16 at 08:35