在 WCF 自托管中第一次失败时,ServiceHost 无法使用新的 ServiceHost 实例再次打开() [英] ServiceHost fail to Open() again with new ServiceHost instance when it failed for the first time in WCF self-host

查看:20
本文介绍了在 WCF 自托管中第一次失败时,ServiceHost 无法使用新的 ServiceHost 实例再次打开()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的症状与这篇文章描述的完全一样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

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.

我的代码与 Dave 的代码略有不同,而他的 ServiceHost 实例(名为 WebService)在 Start() 方法之外.我的 ServiceHost 实例(命名主机)在里面声明.调试的时候,我在Host Description中检查endpoint的地址已经改成正确的IP了.但是,Open() 仍然使用旧的错误 IP 地址引发异常.

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}	The service {1} at {2} is ready", DateTime.Now.ToLongTimeString(), service.ServiceType.ToString(), serverIp));

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

                hostInfo += "Enpoints details:
";
                foreach (var endpt in host.Description.Endpoints)
                {
                    hostInfo += String.Format("	 Name:		{0}
", endpt.Name);
                    hostInfo += String.Format("	 Logical address:	{0}
", endpt.Address);
                    hostInfo += String.Format("	 Physical address:	{0}
", endpt.ListenUri);
                    hostInfo += String.Format("	 Binding:		{0}
", endpt.Binding);
                    hostInfo += String.Format("	 Contract:	{0}

", endpt.Contract.ContractType.Name);
                }
                LogList.Add(hostInfo);
            }
            catch (Exception e)
            {
                host.Abort();
                host = null;
                LogList.Add(String.Format("{0}	{1}", DateTime.Now.ToLongTimeString(), e.Message));
            }
            return true;
        }
        return false;
    }

这是我对 PtiCommunicationService 的 ServiceBehavior

Here is my ServiceBehavior for PtiCommunicationService

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

和接口的 ServiceContract

and ServiceContract for the interface

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

app.config 中没有其他配置.全部都在代码中.

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

谢谢

更新:

我发现我们两个都对 ServiceHost Constructor (Object, Uri[]) 使用了相同的重载,它们构成了 Web 服务的单例.

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.

推荐答案

显然 WCF 缓存了一些套接字信息.我发现的最佳解决方法是由 Ivan 在这里 https://stackoverflow.com/a/6839265/955400 给出的.在尝试调用 host.Open() 之前,您检查是否可以打开连接.

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().

这篇关于在 WCF 自托管中第一次失败时,ServiceHost 无法使用新的 ServiceHost 实例再次打开()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆