locked
Polling Duplex , Channel in Fault State RRS feed

  • Question

  • Hi,

    for notification in  my silverlight client app, I am using WCF pollingDuplex binding.

    Binding Details at server side ...

    PollingDuplexHttp Binding custPollBind = new PollingDuplexHttpBinding();

     custPollBind.InactivityTimeout = TimeSpan.FromDays(12);
                        custPollBind.ReceiveTimeout = TimeSpan.FromDays(12);
                        custPollBind.ServerPollTimeout = TimeSpan.FromSeconds(25);
                        custPollBind.TransferMode = TransferMode.StreamedResponse;
                        custPollBind.MaxOutputDelay = new TimeSpan(0, 0, 7);

    Binding Details At Client Side :

     PollingDuplexHttpBinding binding = new PollingDuplexHttpBinding()
                   {

                       ReceiveTimeout = TimeSpan.FromDays(12),
                       InactivityTimeout = TimeSpan.FromDays(12),
                      
                   };

     EndpointAddress address = new EndpointAddress(endPoint);
                    client = new StuDuplexServiceClient(binding, address);

    I want channel should never go into fault stat.

    For this , also on every minitue I am sending some dummy notification data to keep all connected client or channel alive.

    It is working fine. But After long duration usually 4-5 or 5-6 or some time 2-3 hours all connected channel getting faulted. ANd client app is no more connected to WCF service.

    Once after long duration , if I am refreshing the page or re-connecting the client app, it is connecting , but again after only 10-12 seconds , channel is  becoming faulted state. and you can say , it is connecting for only 10-12 seconds.

    If again I am re-starting my service , then it is working fine. and same problem is contud.... after some time.

    My WCF service is hosted as Windows service.

    For Service Behavior I am using this..

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]

    Is this creating any problem. I have checked by removing this also. but there is no luck.

    Monday, September 26, 2011 10:25 AM

All replies

  • Do you new the proxy everytime you connect to the WCF service? I'd recommend that you do that. This way you are not recycling existing WCF proxy handles that could have been faulted. The newing call is not expensive and will rid you of all the troubles that you are facing. Let me know if it is otherwise.
    Monday, September 26, 2011 1:39 PM
  • What does mean new the proxy everytime while connecting to WCF Service. ?

    Tuesday, September 27, 2011 3:51 AM
  • It means dispose the proxy (null it) and reinitialize it.

    _Proxy = null;
    _Factory = null;
    InitializeProxy(usern, passw)

    private void InitializeProxy(string usern, string passw)
            {
                try
                {
                    MyListCallback callback = new MyListCallback(this);
                    if (_Factory == null)
                        _Factory = new DuplexChannelFactory<IMyListService>(new InstanceContext(callback), "default");
                    ClientCredentials loginCredentials = new ClientCredentials();
                    var defaultCredentials = _Factory.Endpoint.Behaviors.Find<ClientCredentials>();
                    _Factory.Endpoint.Behaviors.Remove(defaultCredentials); //remove default ones
                    loginCredentials.UserName.UserName = usern;
                    loginCredentials.UserName.Password = passw;
                    loginCredentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;
                    _Factory.Endpoint.Behaviors.Add(loginCredentials); //add required ones
                    _Proxy = _Factory.CreateChannel();
                    ICommunicationObject co = _Proxy as ICommunicationObject;
                    co.Closed += new EventHandler(InnerDuplexChannel_Closed);
                    co.Faulted += new EventHandler(InnerDuplexChannel_Faulted);
                    co.Opened += new EventHandler(InnerDuplexChannel_Opened);
                    MyGeo ff;
                    ff = _Proxy.Subscribe();

                    }

               }

    Tuesday, September 27, 2011 10:18 AM
  • it's not working for me. any thing else we can do..

    Friday, September 30, 2011 5:58 AM
  • Tell us what you tried to do and what errors you get, maybe post some of your code. "It's not working" is too little information to work with. 
    Friday, September 30, 2011 9:48 AM
  • Hi Prefix The First

    As you told to post some code, here I am posting same, Please review it, and let me know where am I commit wrong.

    It is working fine. But After long duration usually 4-5 or 5-6 or some time 2-3 hours all connected channel getting faulted. ANd client app is no more connected to WCF service.

    Once after long duration , if I am refreshing the page or re-connecting the client app, it is connecting , but again after only 10-12 seconds , channel is  becoming faulted state. and you can say , it is connecting for only 10-12 seconds.

    If again I am re-starting my service , then it is working fine. and same problem is contud.... after some time.

     

    IEMSClient.cs

     [ServiceContract(Namespace = "EMSDuplexService")]
        public interface IEMSClient
        {

            [OperationContract(IsOneWay = true, AsyncPattern = true)]
            IAsyncResult BeginNotifyNewsFeedResult(string objMessage, AsyncCallback callback, object state);
            [OperationContract(IsOneWay = true, AsyncPattern = true)]
            IAsyncResult BeginNotifyWeatherFeedResult(string objMessage, AsyncCallback callback, object state);
                 /// <summary>
            /// Ends the notify progress.
            /// </summary>
            /// <param name="result">The result.</param>
                 void EndNotifyNewsFeedResult(IAsyncResult result);
            void EndNotifyWeatherFeedResult(IAsyncResult result);
                }

    IEMSService.cs

    [ServiceContract(Namespace="EMSDuplexService", CallbackContract=typeof(IEMSClient))]
        public interface IEMSDuplexService
        {
            [OperationContract(IsOneWay = true)]
            void GetClientRequest(string objReceiveMessage);
        }

     

      [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
        public class DBMDetails : IPolicyRetriever,IEMSDuplexService
        {

     #region IEMSDuplexService Members

            /// <summary>
            /// list of Silverlight client.
            /// </summary>
            static List<IEMSClient> m_Callbacks = new List<IEMSClient>();
            static List<IEMSClient> objRemoveCallBack = new List<IEMSClient>();
      
           
            /// <summary>
            /// This method will fire once a new silverlight interface has launched.
            /// </summary>
            /// <param name="objReceiveMessage"></param>
            public void GetClientRequest(string objReceiveMessage)
            {
             
                IEMSClient _Client = OperationContext.Current.GetCallbackChannel<IEMSClient>();
                ((ICommunicationObject)_Client).Closed += new EventHandler(DBMDetails_Closed);
                ((ICommunicationObject)_Client).Faulted += new EventHandler(DBMDetails_Faulted);
        
                if (!m_Callbacks.Contains(_Client))
                {
                    Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff") + " New Client Connected");
                    Program.WriteToLog("New Client Connected");
                    m_Callbacks.Add(_Client);
                }
             
            }
               void CallBackScheduler_EventWeatherFeed(string strFeeds)
            {
                if (!string.IsNullOrEmpty(strFeeds))
                    SendWeatherFeedCallBack(strFeeds);
            }
            void CallBackScheduler_EventNewsFeed(string strFeeds)
            {
                if (!string.IsNullOrEmpty(strFeeds))
                    SendNewsFeedCallBack(strFeeds);  
            }
           public void SendNewsFeedCallBack(string obj)
            {
                try
                {
                    if (m_Callbacks.Count == 0)
                        Program.WriteToLog("No of call back client is Zero");
                   
                    m_Callbacks.ForEach(delegate(IEMSClient callback)
                    {
                        Program.WriteToLog("News Feed Call back Sent");
                        callback.BeginNotifyNewsFeedResult(obj, r =>
                        {
                            try
                            {
                                callback.EndNotifyNewsFeedResult(r);
                            }
                            catch (Exception ex)
                            {
                                // client disconnected.
                                // nothing to do here...
                                objRemoveCallBack.Add(callback);
                                Program.WriteToLog(ex.ToString());
                            }
                        }, null);
                    });
                    foreach (IEMSClient objCallback in objRemoveCallBack)
                    {
                        Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff") + " Client Connection Faulted");
                        Program.WriteToLog("News Feed CallBack :Client Connection Faulted");
                        m_Callbacks.Remove(objCallback);
                    }
                    objRemoveCallBack.Clear();
                }
                catch (Exception ex)
                {
                    Program.WriteToLog(ex.ToString());
                }
            }
            public void SendWeatherFeedCallBack(string obj)
            {
                try
                {
                    if (m_Callbacks.Count == 0)
                        Program.WriteToLog("No of call back client is Zero");
                    m_Callbacks.ForEach(delegate(IEMSClient callback)
                    {
                        Program.WriteToLog("Weather CallBack Sent");
                        // Message objDataMsg = Message.CreateMessage(
                        //MessageVersion.Soap11,
                        //"EMSDuplexService/IEMSDuplexService/ResponseToClient", obj);
                        callback.BeginNotifyWeatherFeedResult(obj, r =>
                        {
                            try
                            {
                                callback.EndNotifyWeatherFeedResult(r);
                            }
                            catch (Exception ex)
                            {
                                // client disconnected.
                                // nothing to do here...
                               objRemoveCallBack.Add(callback);
                                Program.WriteToLog(ex.ToString());
                            }
                        }, null);
                    });
                    foreach (IEMSClient objCallback in objRemoveCallBack)
                    {
                        Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff") + " Client Connection Faulted");
                        Program.WriteToLog("Weather Feed CallBack :Client Connection Faulted");
                        m_Callbacks.Remove(objCallback);
                    }
                    objRemoveCallBack.Clear();
                }
                catch (Exception ex)
                {
                    Program.WriteToLog(ex.ToString());
                }
            }
                   /// <summary>
            /// This method will fire once , any connection has faulted
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            public void DBMDetails_Faulted(object sender, EventArgs e)
            {
                ///if client connection is dead or has been closed , remove that object from client list.
                try
                {
                    IEMSClient client = sender as IEMSClient;

                    Program.WriteToLog("Client Faulted");
                    if (client != null)
                    {
                        Program.WriteToLog("No of CallBack Client Before Remove :" + m_Callbacks.Count);
                        m_Callbacks.Remove(client);
                        Program.WriteToLog("No of CallBack Client After Remove :" + m_Callbacks.Count);
                    }
                }
                catch (Exception ex)
                {
                    Program.WriteToLog(ex.ToString());
                }
            }
            /// <summary>
            /// This method will fire once any connection has closed.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            public void DBMDetails_Closed(object sender, EventArgs e)
            {
                ///if client connection is dead or has been closed , remove that object from client list.
                try
                {
                    IEMSClient client = sender as IEMSClient;
                    Program.WriteToLog("Client Connection Closed.");
                    if (client != null)
                    {
                        Program.WriteToLog("No of CallBack Client Before Remove :" + m_Callbacks.Count);
                        m_Callbacks.Remove(client);
                        Program.WriteToLog("No of CallBack Client After Remove :" + m_Callbacks.Count);
                    }
                }
                catch (Exception ex)
                {
                    Program.WriteToLog(ex.ToString());
                }
            }

            #endregion

     


     class Program
        {
                  static void Main(string[] args)
            {
              
                    DateTime dt = Convert.ToDateTime("2011/12/31");
                    // Step 1 of the address configuration procedure: Create a URI to serve as the base address.
                    DateTime p = dt;
                    Uri baseAddress;
                    String IP = Program.GetIPAddress();
                    if (!string.IsNullOrEmpty(IP))
                    {
                        baseAddress = new Uri("http://" + IP + ":8000");
                    }
                    else
                    {
                        baseAddress = new Uri("http://localhost:8000");
                    }

                    Thread th = new Thread(new ThreadStart(Program.ProcessLogQueue));
                    th.IsBackground = true;
                    th.Start();

                    // Step 2 of the hosting procedure: Create ServiceHost
                    ServiceHost selfHost = new ServiceHost(typeof(XmlRead), baseAddress);
               


                    try
                    {

                        // Create a binding to use.
                        BasicHttpBinding binding = new BasicHttpBinding();
                        //   binding.Security.Mode = BasicHttpSecurityMode.Message;
                        binding.MaxBufferSize = 2147483647;
                        binding.MaxReceivedMessageSize = 2147483647;
                        binding.ReaderQuotas.MaxBytesPerRead = 2147483647;
                        binding.ReaderQuotas.MaxArrayLength = 2147483647;
                        binding.ReaderQuotas.MaxStringContentLength = 2147483647;
                        binding.ReaderQuotas.MaxDepth = 2147483647;
                     


                        PollingDuplexHttpBinding custPollBind = new PollingDuplexHttpBinding();
                        custPollBind.InactivityTimeout = TimeSpan.FromHours(12);
                        custPollBind.ReceiveTimeout = TimeSpan.FromHours(12);
                        custPollBind.ServerPollTimeout = TimeSpan.FromSeconds(25);
                        custPollBind.TransferMode = TransferMode.StreamedResponse;
                        custPollBind.DuplexMode = PollingDuplexMode.MultipleMessagesPerPoll;
                        custPollBind.MaxOutputDelay = new TimeSpan(0, 0, 7);

     

                        WSDualHttpBinding wsDualBinding = new WSDualHttpBinding();
                        if (!string.IsNullOrEmpty(IP))
                        {
                            wsDualBinding.ClientBaseAddress = new Uri("http://" + IP + ":8001/AlertMessage");
                        }
                        else
                        {
                            wsDualBinding.ClientBaseAddress = new Uri("http://localhost:8001/AlertMessage");
                        }
                        wsDualBinding.ReceiveTimeout = TimeSpan.MaxValue;
                        wsDualBinding.ReliableSession.InactivityTimeout = TimeSpan.MaxValue;
                        wsDualBinding.SendTimeout = TimeSpan.MaxValue;
                        wsDualBinding.Security.Mode = WSDualHttpSecurityMode.None;

                        // Step 3 of the hosting procedure: Add a service endpoint.
                        selfHost.AddServiceEndpoint(typeof(IEventsDuplex), wsDualBinding, "AlertCallBack");
                        selfHost.AddServiceEndpoint(typeof(IDBMDetails), binding, "DbmDetailsService");
                      
                        selfHost.AddServiceEndpoint(typeof(IXmlRead), new BasicHttpBinding(), "XMLReadClassService");
                      
                        selfHost.AddServiceEndpoint(typeof(IEMSDuplexService), custPollBind, "SelfPolling");
                       
                        selfHost.AddServiceEndpoint(typeof(IPolicyRetriever), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
                       

                        // Step 4 of the hosting procedure: Enable metadata exchange.
                        ServiceMetadataBehavior smb = new ServiceMetadataBehavior();

                        smb.HttpGetEnabled = true;
                        selfHost.Description.Behaviors.Add(smb);

                        // Step 5 of the hosting procedure: Start (and then stop) the service.
                        selfHost.Open();
                        schedule = new StartupSchedule();
                        WriteToLog("The service is ready.");

                        selfHost.Close();

                    }

                    catch (CommunicationException ce)
                    {
                        WriteToLog("An exception occurred: " + ce.ToString());
                        Console.WriteLine("An exception occurred: {0}", ce.Message);
                        selfHost.Abort();
                    }

                    catch (Exception ex)
                    {
                        WriteToLog(ex.ToString());
                    }
                    finally
                    {
                      
                    }

                }
             
            }
        }


    As I told apart from PollingDuplex binding I am also binding some more like basichttpbinding and WSdualhttpbing for  which I am not going to expose the code.


    Binding code form silverlight 4 client app. This App I have converted from silverlgiht 2 to 4.

    Binding Details

    #region Duplex Communication Initialization Area
           EMSDuplexServiceClient client = null;
           public void InitializCallBackCommunication()
           {
               try
               {
                 //  bool status = WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
                 
                   PollingDuplexHttpBinding binding = new PollingDuplexHttpBinding()
                   {

                       ReceiveTimeout = TimeSpan.FromHours(12),
                       InactivityTimeout = TimeSpan.FromHours(12),
                       DuplexMode=PollingDuplexMode.MultipleMessagesPerPoll,
                      
                     
                   };
                   string endPoint = ListofProperty.getAppSetting("CallBackEndPoint");
                   if (string.IsNullOrEmpty(endPoint))
                   {
                       System.Windows.Browser.HtmlPage.Window.Alert("CallBack EndPoint is not Configured");
                       return;
                   }
                  
                   EndpointAddress address = new EndpointAddress(endPoint);
                    client = new EMSDuplexServiceClient(binding, address);
                                 client.NotifyNewsFeedResultReceived += new EventHandler<NotifyNewsFeedResultReceivedEventArgs>(client_NotifyNewsFeedResultReceived);
                   client.NotifyWeatherFeedResultReceived += new EventHandler<NotifyWeatherFeedResultReceivedEventArgs>(client_NotifyWeatherFeedResultReceived);
                   client.InnerChannel.Faulted += new EventHandler(InnerChannel_Faulted);
                   client.InnerChannel.Closed += new EventHandler(InnerChannel_Closed);
                   client.GetClientRequestAsync("");
                   if (iAmAlive == null)
                   {
                       iAmAlive = new DispatcherTimer();
                       iAmAlive.Tick += new EventHandler(iAmAlive_Tick);
                       iAmAlive.Interval = new TimeSpan(0, 0, 5);
                       iAmAlive.Start();
                   }
               }
               catch (Exception ex)
               {
                   client = null;
                   ListofProperty.WriteToLog(ex.ToString());
               }
           }

           void iAmAlive_Tick(object sender, EventArgs e)
           {
               if (client.State == CommunicationState.Closed)
               {
                   try
                   {
                       InitializCallBackCommunication();
                   }
                   catch (Exception ex)
                   {
                       ListofProperty.WriteToLog(ex.ToString());
                   }
               }
           }

           void InnerChannel_Closed(object sender, EventArgs e)
           {
              
           }

           void InnerChannel_Faulted(object sender, EventArgs e)
           {
             
           }

           void client_NotifyWeatherFeedResultReceived(object sender, NotifyWeatherFeedResultReceivedEventArgs e)
           {
           }

           void client_NotifyNewsFeedResultReceived(object sender, NotifyNewsFeedResultReceivedEventArgs e)
           {
             
           }

                 
            #endregion

    Friday, October 7, 2011 10:28 AM
  • Hello Arun,

    I have read your post and I have been facing a very similar issue. It is bugging me for quite some time now and i want to know if you have come across any solution. Thanks a lot.

     

    Omer


    • Edited by Omer Javed Wednesday, November 2, 2011 7:52 AM
    Wednesday, November 2, 2011 7:49 AM
  • Omer and Arun,

    If you want you can send me your project at clydeveldkamp@hotmail.com and i will have a look.

    Wednesday, November 2, 2011 10:13 AM
  • Hi Prefix The First

     

    if you don't mind , here I cann't send any technical data to anybody , for that I am not liable. please help me in some other way.


    Arun K
    Friday, December 2, 2011 8:37 AM
  • Hello Arun,

    I am not sure if this is going to help your cause but i got some help from following blog : http://weblogs.asp.net/alexeyzakharov/archive/2009/04/17/silverlight-tip-problems-with-polling-duplex-inactivitytimeout.aspx

    Look for the November 11 comments. I think the solution lies in finding the correct configuration. I have managed to solve Channel Faulted issue by following configuration :

     

    duplexMode="SingleMessagePerPoll"

    inactivityTimeout="00:01:00"

    receiveTimeout="10:00:00"

     

    However the error still pops its ugly head (although less frequently) during development phase especially when i am using build configuration as Debug. It happens to occur less frequently if i set it to Release. Please share your experience / solution.

     

    Thanks,

    Omer Javed

     

     


    Never give up!
    Friday, December 2, 2011 1:16 PM
  • Hi Arun K, sorry for the late reply

    Did you ever solve this?  We are facing the same issue and can't seem to find a setting or solution

    Thanks in advance

    Friday, October 23, 2015 8:09 PM