简体   繁体   中英

ServiceHost fail to Open() again with new ServiceHost instance when it failed for the first time in WCF self-host

My symptom is exactly as this post described http://social.msdn.microsoft.com/Forums/vstudio/en-US/302ca96e-a810-4958-9905-90ba1175765d/servicehost-does-not-detech-endpoints-cant-recover-from-a-faulted-state

I wonder if this is a known bug.

My code is slightly different from Dave's whereas his ServiceHost instance (named WebService) is outside of Start() method. My ServiceHost instance (named host) is declared inside. When debugging, I check in Host Description that the address of endpoints has changed to the correct IP. However, the Open() still throws an exception with the old wrong IP address.

    private bool InitHost(PtiType type, string serverIp, int portNumber)
    {
        if (!HostDictionary.ContainsKey(type))
        {
            Uri addressBase = new Uri(String.Format("net.tcp://{0}:{1}/CommunicationService/{2}", serverIp, portNumber.ToString(), type.ToString()));
            var service = new PtiCommunicationService(type);

            service.ClientConnected += service_ClientConnected;
            service.ClientBroadcasted += service_ClientBroadcasted;
            service.ClientSentTo += service_ClientSentTo;
            service.ClientDisconnected += service_ClientDisconnected;

            var host = new ServiceHost(service, addressBase);

            //For publishing metadata only
            //Define Metadata endPoint, So we can publish information about the service
            ServiceMetadataBehavior mBehave = new ServiceMetadataBehavior();
            host.Description.Behaviors.Add(mBehave);

            //Enable debug info in fault
            ((ServiceDebugBehavior)host.Description.Behaviors[typeof(ServiceDebugBehavior)]).IncludeExceptionDetailInFaults=true;

            host.AddServiceEndpoint(typeof(IPtiCommunication), new NetTcpBinding(SecurityMode.None), "");
            host.AddServiceEndpoint(typeof(IMetadataExchange),
                MetadataExchangeBindings.CreateMexTcpBinding(),
                "mex");

            try
            {
                host.Open();

                //Add host to dictionary to keep track
                HostDictionary.Add(type, host);

                LogList.Add(String.Format("{0}\tThe service {1} at {2} is ready", DateTime.Now.ToLongTimeString(), service.ServiceType.ToString(), serverIp));

                string hostInfo = String.Format("{0}\tHost information:\n", DateTime.Now.ToLongTimeString());

                hostInfo += "Enpoints details:\n";
                foreach (var endpt in host.Description.Endpoints)
                {
                    hostInfo += String.Format("\t Name:\t\t{0}\n", endpt.Name);
                    hostInfo += String.Format("\t Logical address:\t{0}\n", endpt.Address);
                    hostInfo += String.Format("\t Physical address:\t{0}\n", endpt.ListenUri);
                    hostInfo += String.Format("\t Binding:\t\t{0}\n", endpt.Binding);
                    hostInfo += String.Format("\t Contract:\t{0}\n\n", endpt.Contract.ContractType.Name);
                }
                LogList.Add(hostInfo);
            }
            catch (Exception e)
            {
                host.Abort();
                host = null;
                LogList.Add(String.Format("{0}\t{1}", DateTime.Now.ToLongTimeString(), e.Message));
            }
            return true;
        }
        return false;
    }

Here is my ServiceBehavior for PtiCommunicationService

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

and ServiceContract for the interface

[ServiceContract(CallbackContract = typeof(IPtiCommunicationCallback), SessionMode = SessionMode.Required)]

There is no other configurations in app.config. All are in the code.

Thanks

UPDATE:

I've discovered that both of us use the same overload for ServiceHost Constructor (Object, Uri[]) which make a singleton of web service.

When we create new Service Host with the same singleton, somehow changing endpoint address doesn't take into affect because the instance of the service is still there even though the host has been aborted.

Is there any solution to clean up that singleton when we create new host?

That's my suspicion so far, please correct me if I'm wrong.

Apparently WCF caches some socket information. The best workaround I have found was given by Ivan here https://stackoverflow.com/a/6839265/955400 . You check if you can open the connection before attempting to call host.Open().

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM