学会WCF之试错法——超时

服务契约

[ServiceContract]
    public interface IService
    {
        [OperationContract]
        string GetData(int value);

        [OperationContract]
        string GetString(string value);

        [OperationContract]
        void Upload(Request request);
    }

    [MessageContract]
    public class Request
    {
        [MessageHeader(MustUnderstand = true)]
        public string FileName { get; set; }

        [MessageBodyMember(Order = 1)]
        public Stream Content {get;set;}
}

服务

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Reentrant)]
    public class Service : IService
    {
        public string GetData(int value)
        {
            //Thread.Sleep(120000);
            return string.Format("You entered: {0}", value);
        }

        public string GetString(string value)
        {
            //Thread.Sleep(120000);
            return string.Format("You entered: {0}", value);
        }

        public void Upload(Request request)
        {
            try
            {
                StreamReader sr = new StreamReader(request.Content, Encoding.GetEncoding("GB2312"));
                StreamWriter sw = new StreamWriter("E:\\" + request.FileName + ".txt", false, Encoding.GetEncoding("GB2312"));
                while (!sr.EndOfStream)
                {
                    sw.WriteLine(sr.ReadLine());
                    //Thread.Sleep(5000);
                }
                sr.Close();
                sw.Close();
            }
            catch (Exception ex)
            { }
            
        }
}

服务配置

<system.serviceModel>
    <services>
      <service name="WCF_Find_Error_Lib.Service">
        <endpoint address="" binding="basicHttpBinding" contract="WCF_Find_Error_Lib.IService">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost/S" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

客户端代理

public class ServiceProxy
    {
        public string GetData(int value)
        {
            string ret = null;
            ServiceClient client = null;
            try
            {
                client = new ServiceClient();
                ret = client.GetData(value);
                client.Close();
            }
            catch
            {
                if (client != null)
                {
                    client.Abort();
                }
                throw;
            }
            return ret;
        }

        public string GetString(string value)
        {
            string ret = null;
            ServiceClient client = null;
            try
            {
                client = new ServiceClient();
                ret = client.GetString(value);
                client.Close();
            }
            catch
            {
                if (client != null)
                {
                    client.Abort();
                }
                throw;
            }
            return ret;
        }
        public void Upload(Request request)
        {
            ServiceClient client = null;
            try
            {
                client = new ServiceClient();
                client.Upload(request);
                client.Close();
            }
            catch
            {
                if (client != null)
                {
                    client.Abort();
                }
                throw;
            }
        }

    }


    [ServiceContractAttribute(ConfigurationName = "IService")]
    public interface IService
    {

        [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IService/GetData", ReplyAction = "http://tempuri.org/IService/GetDataResponse")]
        string GetData(int value);

        [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IService/GetString", ReplyAction = "http://tempuri.org/IService/GetStringResponse")]
        string GetString(string value);

        [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IService/Upload", ReplyAction = "http://tempuri.org/IService/UploadResponse")]
        void Upload(Request request);
    }
    [MessageContract]
    public class Request
    {
        [MessageHeader(MustUnderstand = true)]
        public string FileName { get; set; }

        [MessageBodyMember(Order = 1)]
        public Stream Content { get; set; }
}
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Reentrant)]
    public class ServiceClient : System.ServiceModel.ClientBase<IService>, IService
    {

        public ServiceClient()
        {
        }

        public string GetData(int value)
        {
            return base.Channel.GetData(value);
        }

        public string GetString(string value)
        {
            return base.Channel.GetString(value);
        }

        public void Upload(Request request) 
        {
            base.Channel.Upload(request);
        }
}

客户端配置

<system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IService" />
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost/S" binding="basicHttpBinding"
          bindingConfiguration="BasicHttpBinding_IService" contract="IService"
          name="BasicHttpBinding_IService" />
    </client>
  </system.serviceModel>

1 客户端调用超时

运行客户端,执行调用

ServiceProxy proxy = new ServiceProxy();

string s = proxy.GetData(1);

通过配置sendTimeout参数设定超时时间,超时时间默认为1分钟,上述配置中采用了默认超时时间。

Message

请求通道在等待 00:00:59.9469970 以后答复时超时。增加传递给请求调用的超时值,或者增加绑定上的 SendTimeout 值。分配给此操作的时间可能已经是更长超时的一部分。

Stacktrace:

Server stack trace:

在 System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)

在 System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)

在 System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)

在 System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)

在 System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]:

在 System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)

在 System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)

在 Client.IService.GetData(Int32 value)

在 Client.ServiceClient.GetData(Int32 value) 位置 e:\projgxz_myself\WCF_Find_Error\Client\ServiceProxy.cs:行号 52

在 Client.ServiceProxy.GetData(Int32 value) 位置 e:\projgxz_myself\WCF_Find_Error\Client\ServiceProxy.cs:行号 19

在 Client.Program.Main(String[] args) 位置 e:\projgxz_myself\WCF_Find_Error\Client\Program.cs:行号 17

增大客户端调用超时时间,可解决超时问题

例如,超时时间设置为10分钟,满足此次调用需求。

<system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IService" sendTimeout="00:10:00"/>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost/S" binding="basicHttpBinding"
          bindingConfiguration="BasicHttpBinding_IService" contract="IService"
          name="BasicHttpBinding_IService" />
    </client>
  </system.serviceModel>

2 非活动状态的最大时间间隔

通过配置receiveTimeout设定时间间隔,默认值为 10 分钟。

服务实例化模式改为为会话模式:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Reentrant)]

服务端配置

<netTcpBinding>
     <binding name="NetTcpBinding_IService" maxBufferSize="270000" maxReceivedMessageSize="270000" transferMode="Buffered" receiveTimeout="00:00:10">
       <readerQuotas maxStringContentLength="240000"/>
       <reliableSession enabled="true" inactivityTimeout="00:00:10"/>
     </binding>
</netTcpBinding>

客户端配置

<netTcpBinding>
     <binding name="NetTcpBinding_IService" sendTimeout="00:00:10" maxBufferSize="2700000" maxReceivedMessageSize="2700000" transferMode="Buffered" >
       <readerQuotas maxStringContentLength="240000"/>
     </binding>
</netTcpBinding>

客户端调用

using (ServiceClient client = new ServiceClient())
                {
                    StreamReader sr = new StreamReader("D:\\CSBMTEMP.txt", Encoding.Default);
                    string str = sr.ReadToEnd();
                    sr.Close();
                    client.GetString(str);

                    Thread.Sleep(100000);
                    client.GetString(str);
                }

运行客户端程序,成功捕获异常

上述异常中给出的错误信息并未指出具体的异常原因,所以从中很难推测是由于超时时间设置问题。遇到此类问题只能根据经验逐项排查,当然这是很浪费时间的,尤其是对于复杂的程序,更是如此。

-----------------------------------------------------------------------------------------

时间仓促,水平有限,如有不当之处,欢迎指正。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏finleyMa

GraphQL 分享 实战篇

三种基本操作 Query(a read‐only fetch), Mutation(a write followed by a fetch), Subscrip...

30240
来自专栏思考的代码世界

Python网络数据采集之HTML解析|第01天

假如我们确定一个我们需要采集的目标信息,可能是一组统计数据、或者一个 title等,但是此时这个目标可能藏的比较深,可能在第20层的标签里面,你可能会用下面的方...

19440
来自专栏技术碎碎念

读取含有BOM头的文件遇到的问题

需求是读取一个csv文件,然后解析成对应的数据结构。csv必须包含指定的某些列,通过列名header来进行校验。 解析配置文件的方法。 1 public Li...

38170
来自专栏移动开发之家

Flutter完整开发实战详解(一、Dart语言和Flutter基础)

 在如今的 Fultter 大潮下,本系列是让你看完会安心的文章。本系列将完整讲述:如何快速从0开发一个完整的 Flutter APP,配套高完成度 Flut...

1.3K30
来自专栏GIS讲堂

Arcgis for Js实现graphiclayer的空间查询(续)

上文中,实现了简单的针对graphiclayer的空间查询工作,在本节,将更加详细的介绍针对graphiclayer的空间查询。首先,空间查询的方式:提供多种类...

12230
来自专栏hotqin888的专栏

bootstrap table x-editable select2——带图标的选择

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hotqin888/article/det...

1.4K10
来自专栏移动开发之家

Flutter完整开发实战详解(一、Dart语言和Flutter基础)

 在如今的 Fultter 大潮下,本系列是让你看完会安心的文章。本系列将完整讲述:如何快速从0开发一个完整的 Flutter APP,配套高完成度 Flut...

25820
来自专栏GreenLeaves

C# 文件操作系列一

在.Net环境中,所有关于文件操作的类都在System.IO命名空间下,注:在修改文件时,安全性显得格外重要,但是本随笔不过多讲述安全性,这里假设我们有足够的权...

27750
来自专栏玄魂工作室

如何将HTML字符转换为DOM节点并动态添加到文档中

将字符串动态转换为DOM节点,在开发中经常遇到,尤其在模板引擎中更是不可或缺的技术。 字符串转换为DOM节点本身并不难,本篇文章主要涉及两个主题:<br />

19420
来自专栏菩提树下的杨过

Silverlight:Dependency Property(依赖属性)学习笔记

学习SL/WPF,Dependency Properties(依赖属性)是一个全新(陌生)但又无法回避的概念。 http://www.wpftutorial.n...

20770

扫码关注云+社区

领取腾讯云代金券