none
通信对象 System.ServiceModel.Channels.ClientPollingDuplexSessionChannel 无法用于通信,因为其处于“出错”状态。 RRS feed

  • 问题

  • 服务端配置Web.config这个就是一个普通的WCF工程
    <?xml version="1.0"?>
    
    <configuration>
    
     <system.web>
    
     <compilation debug="true" targetFramework="4.0" />
    
     </system.web>
    
     <connectionStrings>
    
     <add name="ServiceSQL" providerName="System.Data.SqlClient" connectionString="Data Source=127.0.0.1;Initial Catalog=chat;Persist Security Info=True;User ID=sa;Password=sa" />
    
     </connectionStrings>
    
     <system.webServer>
    
     <modules runAllManagedModulesForAllRequests="true"/>
    
     </system.webServer>
    
     
    
     <system.serviceModel>
    
     
    
      <!-- Register the binding extension from the SDK. -->
    
      <extensions>
    
       <bindingExtensions>
    
       <add name="pollingDuplexHttpBinding"
    
         type="System.ServiceModel.Configuration.PollingDuplexHttpBindingCollectionElement,
    
          System.ServiceModel.PollingDuplex, 
    
          Version=4.0.0.0, 
    
          Culture=neutral, 
    
          PublicKeyToken=31bf3856ad364e35" />
    
       </bindingExtensions>
    
      </extensions>
    
     <!-- Create the polling duplex binding. -->
    
     <bindings>
    
      <pollingDuplexHttpBinding>
    
      <binding name="multipleMessagesPerPollPollingDuplexHttpBinding" duplexMode="MultipleMessagesPerPoll" maxOutputDelay="00:00:07"/>
    
      </pollingDuplexHttpBinding>
    
     </bindings>
    
     <services>
    
      <service name="SL.WCF.Services.ChatService" behaviorConfiguration="SL.WCF.Services.ChatBehavior">
    
    
    
      <!-- Service Endpoints -->
    
      <endpoint
    
       address=""
    
       binding="pollingDuplexHttpBinding"
    
       bindingConfiguration="multipleMessagesPerPollPollingDuplexHttpBinding"
    
       contract="SL.WCF.Services.IChatService">
    
      </endpoint>
    
      <endpoint
    
       address="mex"
    
       binding="mexHttpBinding"
    
       contract="IMetadataExchange"/>
    
      </service>
    
     </services>
    
      
    
      <behaviors>
    
       <serviceBehaviors>
    
        <behavior name="SL.WCF.Services.ChatBehavior">
    
         <serviceMetadata httpGetEnabled="true" />
    
         <!--调试异常生产改为false-->
    
         <serviceDebug includeExceptionDetailInFaults="true" />
    
        </behavior>
    
       </serviceBehaviors>
    
      </behaviors>
    
     
    
     
    
     <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    
     </system.serviceModel>
    
     <system.diagnostics>
    
     <sources>
    
      <source name ="System.ServiceModel" switchValue="Verbose">
    
      <listeners>
    
       <add name="xml" />
    
      </listeners>
    
      </source>
    
      <source name ="System.ServiceModel.MessageLogging"
    
        switchValue="Verbose, ActivityTracing">
    
      <listeners>
    
       <add name="xml" />
    
      </listeners>
    
      </source>
    
      <source name ="System.Runtime.Serialization" switchValue="Verbose">
    
      <listeners>
    
       <add name="xml" />
    
      </listeners>
    
      </source>
    
     </sources>
    
     <sharedListeners>
    
      <add name="xml" type="System.Diagnostics.XmlWriterTraceListener"
    
       traceOutputOptions="LogicalOperationStack"
    
       initializeData="C:\log\WCFTrace.svclog" />
    
     </sharedListeners>
    
     <trace autoflush="true" />
    
     </system.diagnostics>
    
     <system.serviceModel>
    
     <diagnostics>
    
      <messageLogging
    
       logEntireMessage="true"
    
       logMalformedMessages="false"
    
       logMessagesAtServiceLevel="true"
    
       logMessagesAtTransportLevel="false"/>
    
     </diagnostics>
    
     </system.serviceModel>
    
    
    
    </configuration>
    
    
    服务代码为:
    namespace SL.WCF.Services
    
    {
    
     // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IChatService" in both code and config file together.
    
     //客户端调用接口
    
     [ServiceContract(Namespace = "Silverlight", CallbackContract = typeof(IChatClient))]//注册双工
    
     public interface IChatService
    
     {
    
      /// <summary>
    
      /// 登录
    
      /// </summary>
    
      /// <param name="userName">用户名</param>
    
      /// <param name="passWord">密码</param>
    
      [OperationContract]
    
      void login(string userName, string passWord);
    
    
    
      //[OperationContract]
    
      //PlatUserInfo GetUserInfo();
    
    
    
      /// <summary>
    
      /// 注册用户
    
      /// </summary>
    
      /// <param name="userInfo"></param>
    
      /// <returns></returns>
    
      [OperationContract]
    
      void RegisterUser(string userInfoStr);
    
      
    
      /// <summary>
    
      /// 用户登录验证
    
      /// </summary>
    
      /// <param name="userName"></param>
    
      /// <param name="password"></param>
    
      /// <returns></returns>
    
      [OperationContract]
    
      string CheckLogin(string userName, string password);
    
     }
    
    [ServiceContract]
    
    public interface IChatClient
    
    {
    
     /// <summary>
    
     /// 系统消息
    
     /// </summary>
    
     /// <param name="message">返回消息</param>
    
     /// <param name="type">0代表异地登陆,1代表用户名或密码错误,2代表登录成功,3代表新添加用户名已经存在</param>
    
     [OperationContract(IsOneWay = true)]
    
     void rSysMessage(string message, int type);
    
    }
    
    }
     
    客户端就是直接引用的在SL的项目中Web.config
    <configuration>
    为了调用代理方便我把代理拿到环境变量中了
    namespace SL.Env
    {
        public class IMEnvironment
        {
            /// <summary>
            /// 移除事件上绑定的所有委托
            /// </summary>
            /// <param name="sender">触发事件源</param>
            /// <param name="eventName">事件名称</param>
            /// <param name="del">要移除事件对应的委托</param>
            ///  //调用
           //EventHandler del = button3_Click;  //EventHandler委托名根据事件绑定的委托,这里以click事件为例.继承与delegate
           //RemoveAllEvent(sender, "Click", del);
            public static  void RemoveAllEvent(object sender, string eventName, Delegate del)
            {
                Type type = sender.GetType();
                System.Reflection.EventInfo[] eventInfos = type.GetEvents(); //获取所有事件信息
                foreach (System.Reflection.EventInfo var in eventInfos)
                {
                    if (var.Name.Trim().ToUpper() == eventName.Trim().ToUpper())  //移除指定的事件
                    {
                        var.RemoveEventHandler(sender, del);
                    }
                }
            }
            private static ChatServiceClient _proxy = null;
            /// <summary>
            /// 当前代理对象
            /// </summary>
            public static ChatServiceClient Proxy
            {
                get
                {
                    if (_proxy == null)
                    {
                        EndpointAddress address = new EndpointAddress("http://localhost:2930/ChatService.svc");
                        PollingDuplexHttpBinding binding = new PollingDuplexHttpBinding(PollingDuplexMode.MultipleMessagesPerPoll);
                        _proxy = new ChatServiceClient(binding, address);
                    }
                   //RemoveAllEvent(_proxy,"",_proxy.RegisterUserCompleted);
                    return _proxy;
                }
            }
            private static PlatUserInfo _currentUserInfo;
            /// <summary>
            /// 当前登录用户
            /// </summary>
            public static PlatUserInfo CurrentUserInfo
            {
                get { return _currentUserInfo; }
                set
                {
                    _currentUserInfo = value;
                }
            }
        }
    }

    SL页面调用的如下

     void ProvinceCode_SelectChangeEvnet(object sender, SelectionChangedEventArgs e)
            {
                IMEnvironment.Proxy.GetRegionCodeAsync(this.ProvinceCode.SelectedValue);
                IMEnvironment.Proxy.GetRegionCodeCompleted += (ss, ee) =>
                {
                    cities = JavaScriptConvert.DeserializeObject<DictRegionCollection>(ee.Result);//e.Result
                    if (cities == null)
                    {
                        return;
                    }
                    else
                    {
                        this.CityCode.ItemsSource = null;
                        var allusers = from x in cities select new DropItem { ValueField = x.RegionCode, DisplayField = x.NameCH };
                        this.CityCode.ItemsSource = new DropItemCollection().AddRange(allusers);
                    }
                };
            }

    但问题是总是时好时坏,大部分情况下是坏的,debug报的错误就是这个


    2011年6月3日 2:18

答案

  • 这是因为WCF 通道有个默认的超时设置,超过一定时间默认会自动回收。 你这里使用了静态属性, public static ChatServiceClient Proxy。 这个方式 可以实现在同一程序集种的客户端代理实例的单例模式。 但是问题是 这个代理会在客户端加载程序集的时候就创建了。 可能出现超时问题,这样代理通道的状态就是Fault。 你在每次使用ChatServiceClient 前判断一下,出错就重新New一次。
    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
     

    老徐的网站】:http://www.frankxulei.com/

    微软WCF中文技术论坛
    微软WCF英文技术论坛

    Windows Azure中文技术论坛

    2011年6月3日 3:04
    版主

全部回复

  • 这是因为WCF 通道有个默认的超时设置,超过一定时间默认会自动回收。 你这里使用了静态属性, public static ChatServiceClient Proxy。 这个方式 可以实现在同一程序集种的客户端代理实例的单例模式。 但是问题是 这个代理会在客户端加载程序集的时候就创建了。 可能出现超时问题,这样代理通道的状态就是Fault。 你在每次使用ChatServiceClient 前判断一下,出错就重新New一次。
    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
     

    老徐的网站】:http://www.frankxulei.com/

    微软WCF中文技术论坛
    微软WCF英文技术论坛

    Windows Azure中文技术论坛

    2011年6月3日 3:04
    版主
  • 嗯,谢谢了我一直在观看你的视频呵呵,很崇拜你,我想问下我这样如果重新new了那服务端我想保存所有在线用户,是不是每个通道对应一个用户呀,还有就是new了以后会话信息的问题,还有一点想问下这个PollingDuplex和net。tcp与SL协作那个效率更高点

    2011年6月3日 3:25